ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/udr/client/FBTransaction.pas
Revision: 371
Committed: Wed Jan 5 15:21:22 2022 UTC (2 years, 3 months ago) by tony
Content type: text/x-pascal
File size: 20676 byte(s)
Log Message:
Beta Release 0.1

File Contents

# User Rev Content
1 tony 45 (*
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 FBTransaction;
63 tony 56 {$IFDEF MSWINDOWS}
64     {$DEFINE WINDOWS}
65     {$ENDIF}
66 tony 45
67     {$IFDEF FPC}
68 tony 56 {$mode delphi}
69 tony 45 {$interfaces COM}
70     {$ENDIF}
71    
72     interface
73    
74     uses
75 tony 359 Classes, SysUtils, IB, FBParamBlock, FBActivityMonitor, FBClientAPI, FBOutputBlock;
76 tony 45
77     type
78     { TFBTransaction }
79    
80     TFBTransaction = class(TActivityReporter, IActivityMonitor,ITransaction)
81     private
82 tony 263 FFirebirdAPI: TFBClientAPI;
83 tony 45 function GenerateTPB(sl: array of byte): ITPB;
84     protected
85     FTPB: ITPB;
86     FSeqNo: integer;
87 tony 363 FDefaultCompletion: TTransactionCompletion;
88 tony 45 FAttachments: array of IAttachment; {Keep reference to attachment - ensures
89     attachment cannot be freed before transaction}
90 tony 363 FTransactionName: AnsiString;
91 tony 371 FForeignHandle: boolean;
92 tony 359 procedure CheckHandle;
93 tony 45 function GetActivityIntf(att: IAttachment): IActivityMonitor; virtual; abstract;
94 tony 363 function GetJournalIntf(Attachment: IAttachment): IJournallingHook;
95 tony 263 procedure SetInterface(api: TFBClientAPI); virtual;
96 tony 359 function GetTrInfo(ReqBuffer: PByte; ReqBufLen: integer): ITrInformation; virtual; abstract;
97 tony 363 procedure InternalStartSingle(attachment: IAttachment); virtual; abstract;
98     procedure InternalStartMultiple; virtual; abstract;
99     procedure InternalCommit(Force: boolean); virtual; abstract;
100     procedure InternalCommitRetaining; virtual; abstract;
101     procedure InternalRollback(Force: boolean); virtual; abstract;
102     procedure InternalRollbackRetaining; virtual; abstract;
103 tony 45 public
104 tony 363 constructor Create(api: TFBClientAPI; Attachments: array of IAttachment; Params: array of byte; DefaultCompletion: TTransactionAction; aName: AnsiString); overload;
105     constructor Create(api: TFBClientAPI; Attachments: array of IAttachment; TPB: ITPB; DefaultCompletion: TTransactionAction; aName: AnsiString); overload;
106     constructor Create(api: TFBClientAPI; Attachment: IAttachment; Params: array of byte; DefaultCompletion: TTransactionAction; aName: AnsiString); overload;
107     constructor Create(api: TFBClientAPI; Attachment: IAttachment; TPB: ITPB; DefaultCompletion: TTransactionAction; aName: AnsiString); overload;
108 tony 45 destructor Destroy; override;
109     procedure DoDefaultTransactionEnd(Force: boolean);
110 tony 263 property FirebirdAPI: TFBClientAPI read FFirebirdAPI;
111 tony 45
112     public
113     {ITransaction}
114     function getTPB: ITPB;
115     procedure PrepareForCommit;virtual; abstract;
116 tony 363 procedure Commit(Force: boolean=false);
117     procedure CommitRetaining;
118 tony 45 function GetInTransaction: boolean; virtual; abstract;
119 tony 359 function GetIsReadOnly: boolean;
120     function GetTransactionID: integer;
121 tony 45 function GetAttachmentCount: integer;
122     function GetAttachment(index: integer): IAttachment;
123 tony 363 function GetJournalingActive(attachment: IAttachment): boolean;
124     function GetDefaultCompletion: TTransactionCompletion;
125     procedure Rollback(Force: boolean=false);
126     procedure RollbackRetaining;
127     procedure Start(DefaultCompletion: TTransactionCompletion=taCommit); overload;
128 tony 45 procedure Start(TPB: ITPB; DefaultCompletion: TTransactionCompletion=taCommit); overload;
129 tony 359 function GetTrInformation(Requests: array of byte): ITrInformation; overload;
130     function GetTrInformation(Request: byte): ITrInformation; overload;
131 tony 363 function GetTransactionName: AnsiString;
132     procedure SetTransactionName(aValue: AnsiString);
133 tony 45
134     property InTransaction: boolean read GetInTransaction;
135     property TransactionSeqNo: integer read FSeqNo;
136     end;
137    
138 tony 315 {The transaction user interface is used to force an action on the end of the
139     transaction.}
140    
141     ITransactionUser = interface
142     ['{156fcdc9-a326-44b3-a82d-f23c6fb9f97c}']
143     procedure TransactionEnding(aTransaction: ITransaction; Force: boolean);
144     end;
145    
146     { TTPBItem }
147    
148     TTPBItem = class(TParamBlockItem,ITPBItem)
149     public
150     function getParamTypeName: AnsiString; override;
151     end;
152    
153     { TTPB }
154    
155     TTPB = class (TCustomParamBlock<TTPBItem,ITPBItem>, ITPB)
156     protected
157     function LookupItemType(ParamTypeName: AnsiString): byte; override;
158     public
159     constructor Create(api: TFBClientAPI);
160 tony 345 function GetParamTypeName(ParamType: byte): Ansistring;
161     {$IFDEF FPC}
162     function ITPB.GetDPBParamTypeName = GetParamTypeName;
163     {$ELSE}
164 tony 315 function GetDPBParamTypeName(ParamType: byte): Ansistring;
165 tony 345 {$ENDIF}
166 tony 363 function AsText: AnsiString;
167 tony 345 end;
168 tony 315
169 tony 359 {$IFDEF FPC}
170     TTrInfoItem = class;
171    
172     { TTrInfoItem }
173    
174     TTrInfoItem = class(TOutputBlockItemGroup<TTrInfoItem,ITrInfoItem>,ITrInfoItem)
175     {$ELSE}
176 tony 363 TTrInfoItem = class(TOutputBlockItemGroup<TOutputBlockItem,ITrInfoItem>,ITrInfoItem)
177 tony 359 {$ENDIF}
178     public
179     procedure DecodeTraIsolation(var IsolationType, RecVersion: byte);
180     end;
181    
182     { TTrInformation }
183    
184     TTrInformation = class(TCustomOutputBlock<TTrInfoItem,ITrInfoItem>, ITrInformation)
185     protected
186     procedure DoParseBuffer; override;
187     public
188     constructor Create(api: TFBClientAPI; aSize: integer = DefaultBufferSize);
189     {$IFNDEF FPC}
190 tony 363 function Find(ItemType: byte): ITrInfoItem;
191 tony 359 {$ENDIF}
192     end;
193    
194 tony 363
195 tony 45 implementation
196    
197 tony 315 uses FBMessages;
198 tony 45
199 tony 315 const
200     isc_tpb_last_tpb_constant = isc_tpb_at_snapshot_number;
201    
202     TPBConstantNames: array[1..isc_tpb_last_tpb_constant] of string = (
203     'consistency',
204     'concurrency',
205     'shared',
206     'protected',
207     'exclusive',
208     'wait',
209     'nowait',
210     'read',
211     'write',
212     'lock_read',
213     'lock_write',
214     'verb_time',
215     'commit_time',
216     'ignore_limbo',
217     'read_committed',
218     'autocommit',
219     'rec_version',
220     'no_rec_version',
221     'restart_requests',
222     'no_auto_undo',
223     'lock_timeout',
224     'read_consistency',
225     'at_snapshot_number'
226     );
227    
228 tony 45 { TFBTransaction }
229    
230     function TFBTransaction.GenerateTPB(sl: array of byte): ITPB;
231     var
232     i: Integer;
233     begin
234 tony 263 Result := TTPB.Create(FFirebirdAPI);
235 tony 45 for i := 0 to Length(sl) - 1 do
236     Result.Add(sl[i]);
237     end;
238    
239 tony 359 procedure TFBTransaction.CheckHandle;
240     begin
241     if not InTransaction then
242     IBError(ibxeNotInTransaction,[]);
243     end;
244    
245 tony 363 function TFBTransaction.GetJournalIntf(Attachment: IAttachment): IJournallingHook;
246     begin
247     Attachment.QueryInterface(IJournallingHook,Result)
248     end;
249    
250 tony 263 procedure TFBTransaction.SetInterface(api: TFBClientAPI);
251     begin
252     FFirebirdAPI := api;
253     end;
254    
255     constructor TFBTransaction.Create(api: TFBClientAPI; Attachments: array of IAttachment;
256 tony 363 Params: array of byte; DefaultCompletion: TTransactionAction; aName: AnsiString);
257 tony 45 begin
258 tony 363 Create(api, Attachments,GenerateTPB(Params), DefaultCompletion, aName);
259 tony 45 end;
260    
261 tony 263 constructor TFBTransaction.Create(api: TFBClientAPI; Attachments: array of IAttachment; TPB: ITPB;
262 tony 363 DefaultCompletion: TTransactionAction; aName: AnsiString);
263 tony 45 var
264     i: Integer;
265     begin
266     inherited Create(nil);
267 tony 363 FTransactionName := aName;
268 tony 263 SetInterface(api);
269 tony 45 if Length(Attachments) = 0 then
270     IBError(ibxeEmptyAttachmentsList,[nil]);
271    
272 tony 263 {make sure all attachments use same Firebird API}
273     for i := 0 to Length(Attachments) - 1 do
274     if Attachments[i].getFirebirdAPI.GetFBLibrary.GetHandle <> FFirebirdAPI.GetFBLibrary.GetHandle then
275     IBError(ibxeDifferentAPIs,[nil]);
276    
277 tony 45 SetLength(FAttachments,Length(Attachments));
278     for i := 0 to Length(Attachments) - 1 do
279     begin
280     AddMonitor(GetActivityIntf(Attachments[i]));
281     FAttachments[i] := Attachments[i];
282     end;
283     FTPB := TPB;
284     Start(DefaultCompletion);
285     end;
286    
287 tony 263 constructor TFBTransaction.Create(api: TFBClientAPI; Attachment: IAttachment;
288 tony 363 Params: array of byte; DefaultCompletion: TTransactionAction; aName: AnsiString);
289 tony 45 begin
290 tony 363 Create(api,Attachment,GenerateTPB(Params),DefaultCompletion,aName);
291 tony 45 end;
292    
293 tony 263 constructor TFBTransaction.Create(api: TFBClientAPI; Attachment: IAttachment; TPB: ITPB;
294 tony 363 DefaultCompletion: TTransactionAction; aName: AnsiString);
295 tony 45 begin
296     inherited Create(nil);
297 tony 263 SetInterface(api);
298 tony 45 AddMonitor(GetActivityIntf(Attachment));
299     SetLength(FAttachments,1);
300     FAttachments[0] := Attachment;
301     FTPB := TPB;
302 tony 363 FTransactionName := aName;
303 tony 45 Start(DefaultCompletion);
304     end;
305    
306     destructor TFBTransaction.Destroy;
307     begin
308     DoDefaultTransactionEnd(false);
309     inherited Destroy;
310     end;
311    
312     procedure TFBTransaction.DoDefaultTransactionEnd(Force: boolean);
313     var i: integer;
314 tony 315 intf: IUnknown;
315     user: ITransactionUser;
316 tony 45 begin
317 tony 371 if InTransaction and not FForeignHandle then
318 tony 45 begin
319     for i := 0 to InterfaceCount - 1 do
320     begin
321     intf := GetInterface(i);
322 tony 315 if (intf <> nil) and (intf.QueryInterface(ITransactionUser,user) = S_OK) then
323     user.TransactionEnding(self,Force);
324 tony 45 end;
325     case FDefaultCompletion of
326     taRollback:
327     Rollback(Force);
328     taCommit:
329     Commit(Force);
330     end;
331     end;
332     end;
333    
334     function TFBTransaction.getTPB: ITPB;
335     begin
336     Result := FTPB;
337     end;
338    
339 tony 363 procedure TFBTransaction.Commit(Force: boolean);
340     var i: integer;
341     TransactionID: integer;
342     TransactionEndNeeded: array of boolean;
343     begin
344     if not GetInTransaction then Exit;
345    
346 tony 371 if FForeignHandle then
347     IBError(ibxeTransactionNotOwned,[nil]);
348    
349 tony 363 SetLength(TransactionEndNeeded,Length(FAttachments));
350     TransactionID := GetTransactionID;
351     for i := 0 to Length(FAttachments) - 1 do
352     if (FAttachments[i] <> nil) then
353     TransactionEndNeeded[i] := GetJournalingActive(FAttachments[i])
354     else
355     TransactionEndNeeded[i] := false;
356     InternalCommit(Force);
357     for i := 0 to Length(FAttachments) - 1 do
358     if TransactionEndNeeded[i] then
359     GetJournalIntf(FAttachments[i]).TransactionEnd(TransactionID, TACommit);
360     end;
361    
362     procedure TFBTransaction.CommitRetaining;
363     var i: integer;
364     TransactionID: integer;
365     begin
366     if not GetInTransaction then Exit;
367    
368     TransactionID := GetTransactionID;
369     InternalCommitRetaining;
370     for i := 0 to Length(FAttachments) - 1 do
371     if (FAttachments[i] <> nil) and GetJournalingActive(FAttachments[i]) then
372     GetJournalIntf(FAttachments[i]).TransactionRetained(self,TransactionID, TACommitRetaining);
373     end;
374    
375 tony 359 function TFBTransaction.GetIsReadOnly: boolean;
376     var Info: ITrInformation;
377     begin
378     Info := GetTrInformation(isc_info_tra_access);
379     if (Info.Count > 0) and (Info[0].getItemType = isc_info_tra_access) then
380     Result := Info[0].getAsInteger = isc_info_tra_readonly
381     else
382     Result := false;
383     end;
384    
385     function TFBTransaction.GetTransactionID: integer;
386     var Info: ITrInformation;
387     begin
388     Result := -1;
389     Info := GetTrInformation(isc_info_tra_id);
390     if (Info.Count > 0) and (Info[0].getItemType = isc_info_tra_id) then
391     Result := Info[0].getAsInteger;
392     end;
393    
394 tony 45 function TFBTransaction.GetAttachmentCount: integer;
395     begin
396     Result := Length(FAttachments);
397     end;
398    
399     function TFBTransaction.GetAttachment(index: integer): IAttachment;
400     begin
401     if (index >= 0) and (index < Length(FAttachments)) then
402     Result := FAttachments[index]
403     else
404     IBError(ibxeAttachmentListIndexError,[index]);
405     end;
406    
407 tony 363 function TFBTransaction.GetJournalingActive(attachment: IAttachment): boolean;
408     begin
409     Result := false;
410     if (attachment = nil) and (length(FAttachments) > 0) then
411     attachment := FAttachments[0];
412     if attachment <> nil then
413     with attachment do
414     Result := self.GetInTransaction and JournalingActive and
415     ((((joReadOnlyTransactions in GetJournalOptions) and self.GetIsReadOnly)) or
416     ((joReadWriteTransactions in GetJournalOptions) and not self.GetIsReadOnly));
417     end;
418    
419     function TFBTransaction.GetDefaultCompletion: TTransactionCompletion;
420     begin
421     Result := FDefaultCompletion;
422     end;
423    
424     procedure TFBTransaction.Rollback(Force: boolean);
425     var i: integer;
426     TransactionID: integer;
427     TransactionEndNeeded: array of boolean;
428     begin
429     if not GetInTransaction then Exit;
430    
431 tony 371 if FForeignHandle then
432     IBError(ibxeTransactionNotOwned,[nil]);
433    
434 tony 363 SetLength(TransactionEndNeeded,Length(FAttachments));
435     TransactionID := GetTransactionID;
436     for i := 0 to Length(FAttachments) - 1 do
437     if (FAttachments[i] <> nil) then
438     TransactionEndNeeded[i] := GetJournalingActive(FAttachments[i])
439     else
440     TransactionEndNeeded[i] := false;
441     InternalRollback(Force);
442     for i := 0 to Length(FAttachments) - 1 do
443     if TransactionEndNeeded[i] then
444     GetJournalIntf(FAttachments[i]).TransactionEnd(TransactionID, TARollback);
445     end;
446    
447     procedure TFBTransaction.RollbackRetaining;
448     var i: integer;
449     TransactionID: integer;
450     begin
451     if not GetInTransaction then Exit;
452    
453     TransactionID := GetTransactionID;
454     InternalRollbackRetaining;
455     for i := 0 to Length(FAttachments) - 1 do
456     if (FAttachments[i] <> nil) and GetJournalingActive(FAttachments[i]) then
457     GetJournalIntf(FAttachments[i]).TransactionRetained(self,TransactionID,TARollbackRetaining);
458     end;
459    
460     procedure TFBTransaction.Start(DefaultCompletion: TTransactionCompletion);
461     var i: integer;
462     begin
463     if GetInTransaction then
464     Exit;
465    
466     FDefaultCompletion := DefaultCompletion;
467    
468     if Length(FAttachments) = 1 then
469     InternalStartSingle(FAttachments[0])
470     else
471     InternalStartMultiple;
472     for i := 0 to Length(FAttachments) - 1 do
473     if (FAttachments[i] <> nil) and GetJournalingActive(FAttachments[i]) then
474     GetJournalIntf(FAttachments[i]).TransactionStart(self);
475     Inc(FSeqNo);
476     end;
477    
478 tony 45 procedure TFBTransaction.Start(TPB: ITPB; DefaultCompletion: TTransactionCompletion
479     );
480     begin
481     FTPB := TPB;
482     Start(DefaultCompletion);
483     end;
484    
485 tony 359 function TFBTransaction.GetTrInformation(Requests: array of byte
486     ): ITrInformation;
487     var ReqBuffer: PByte;
488     i: integer;
489     begin
490     CheckHandle;
491     if Length(Requests) = 1 then
492     Result := GetTrInformation(Requests[0])
493     else
494     begin
495     GetMem(ReqBuffer,Length(Requests));
496     try
497     for i := 0 to Length(Requests) - 1 do
498     ReqBuffer[i] := Requests[i];
499    
500     Result := GetTrInfo(ReqBuffer,Length(Requests));
501    
502     finally
503     FreeMem(ReqBuffer);
504     end;
505     end;
506     end;
507    
508     function TFBTransaction.GetTrInformation(Request: byte): ITrInformation;
509     begin
510     CheckHandle;
511     Result := GetTrInfo(@Request,1);
512     end;
513    
514 tony 363 function TFBTransaction.GetTransactionName: AnsiString;
515     begin
516     Result := FTransactionName;
517     end;
518    
519     procedure TFBTransaction.SetTransactionName(aValue: AnsiString);
520     begin
521     FTransactionName := aValue;
522     end;
523    
524 tony 315 { TTPBItem }
525    
526     function TTPBItem.getParamTypeName: AnsiString;
527     begin
528     Result := TPBPrefix + TPBConstantNames[getParamType];
529     end;
530    
531    
532     {TTPB}
533    
534     constructor TTPB.Create(api: TFBClientAPI);
535     begin
536     inherited Create(api);
537     FDataLength := 1;
538     FBuffer^ := isc_tpb_version3;
539     end;
540    
541 tony 345 function TTPB.GetParamTypeName(ParamType: byte): Ansistring;
542 tony 315 begin
543     if ParamType <= isc_tpb_last_tpb_constant then
544 tony 363 Result := TPBPrefix + TPBConstantNames[ParamType]
545 tony 315 else
546     Result := '';
547     end;
548    
549 tony 363 function TTPB.AsText: AnsiString;
550     var i: integer;
551     begin
552     Result := '[';
553     for i := 0 to getCount - 1 do
554     begin
555     Result := Result + GetParamTypeName(getItems(i).getParamType);
556     if i < getCount - 1 then
557     Result := Result + ',';
558     end;
559     Result := Result + ']';
560     end;
561    
562 tony 345 {$IFNDEF FPC}
563     function TTPB.GetDPBParamTypeName(ParamType: byte): Ansistring;
564     begin
565     Result := GetParamTypeName(ParamType);
566     end;
567     {$ENDIF}
568    
569    
570 tony 315 function TTPB.LookupItemType(ParamTypeName: AnsiString): byte;
571     var i: byte;
572     begin
573     Result := 0;
574     ParamTypeName := LowerCase(ParamTypeName);
575     if (Pos(TPBPrefix, ParamTypeName) = 1) then
576     Delete(ParamTypeName, 1, Length(TPBPrefix));
577    
578     for i := 1 to isc_tpb_last_tpb_constant do
579     if (ParamTypeName = TPBConstantNames[i]) then
580     begin
581     Result := i;
582     break;
583     end;
584     end;
585    
586 tony 359 { TTrInfoItem }
587    
588     procedure TTrInfoItem.DecodeTraIsolation(var IsolationType, RecVersion: byte);
589     begin
590     with FFirebirdClientAPI, ItemData^ do
591     if getItemType = isc_info_tra_isolation then
592     begin
593     if FDataLength = 1 then
594     begin
595     IsolationType := getAsInteger;
596     RecVersion := 0;
597     end
598     else
599     begin
600     IsolationType := (FBufPtr + 3)^;
601     RecVersion := (FBufPtr + 4)^;
602     end
603     end
604     else
605     IBError(ibxeInfoBufferTypeError,[integer(FBufPtr^)]);
606     end;
607    
608     { TTrInformation }
609    
610     procedure TTrInformation.DoParseBuffer;
611     var P: PByte;
612     index: integer;
613     begin
614     P := Buffer;
615     index := 0;
616     SetLength(FItems,0);
617     while (P^ <> isc_info_end) and (P < Buffer + getBufSize) do
618     begin
619     SetLength(FItems,index+1);
620     case byte(P^) of
621     isc_info_tra_id,
622     isc_info_tra_oldest_interesting,
623     isc_info_tra_oldest_active,
624     isc_info_tra_oldest_snapshot,
625     fb_info_tra_snapshot_number,
626     isc_info_tra_lock_timeout:
627     FItems[index] := AddIntegerItem(P);
628    
629     isc_info_tra_isolation,
630     {return transaction isolation mode of current transaction.
631     format of returned clumplets is following:
632    
633     isc_info_tra_isolation,
634     1, isc_info_tra_consistency | isc_info_tra_concurrency
635     |
636     2, isc_info_tra_read_committed,
637     isc_info_tra_no_rec_version | isc_info_tra_rec_version
638    
639     i.e. for read committed transactions returned 2 items while for
640     other transactions returned 1 item}
641    
642     isc_info_tra_access:
643     FItems[index] := AddIntegerItem(P);
644     fb_info_tra_dbpath:
645     FItems[index] := AddStringItem(P);
646     else
647     FItems[index] := AddItem(P);
648     end;
649     P := P + FItems[index]^.FSize;
650     Inc(index);
651     end;
652     end;
653    
654     constructor TTrInformation.Create(api: TFBClientAPI; aSize: integer);
655     begin
656     inherited Create(api,aSize);
657     FIntegerType := dtInteger;
658     end;
659    
660 tony 363 {$IFNDEF FPC}
661     function TTrInformation.Find(ItemType: byte): ITrInfoItem;
662     begin
663     Result := inherited Find(ItemType);
664     if Result.GetSize = 0 then
665     Result := nil;
666     end;
667     {$ENDIF}
668    
669 tony 45 end.
670