37 |
|
interface |
38 |
|
|
39 |
|
uses |
40 |
< |
Classes, SysUtils, FBClientAPI, Firebird, IB, IBExternals, FmtBCD, FBClientLib; |
40 |
> |
Classes, SysUtils, FBClientAPI, Firebird, IB, IBExternals, FmtBCD, FBClientLib, |
41 |
> |
FBActivityMonitor; |
42 |
|
|
43 |
|
type |
44 |
|
|
45 |
|
{ TFB30Status } |
46 |
|
|
47 |
|
TFB30Status = class(TFBStatus,IStatus) |
48 |
< |
private |
48 |
> |
protected |
49 |
|
FStatus: Firebird.IStatus; |
50 |
+ |
FDirty: boolean; |
51 |
|
public |
52 |
+ |
destructor Destroy; override; |
53 |
|
procedure Init; |
54 |
+ |
procedure FreeHandle; |
55 |
|
function InErrorState: boolean; |
56 |
+ |
function Warning: boolean; |
57 |
|
function GetStatus: Firebird.IStatus; |
58 |
|
function StatusVector: PStatusVector; override; |
59 |
+ |
property Dirty: boolean read FDirty; |
60 |
|
end; |
61 |
|
|
62 |
|
{ TFB30StatusObject } |
63 |
|
|
64 |
|
TFB30StatusObject = class(TFB30Status) |
65 |
|
public |
66 |
< |
constructor Create(aOwner: TFBClientAPI; status: Firebird.IStatus); |
66 |
> |
constructor Create(aOwner: TFBClientAPI; status: Firebird.IStatus; prefix: Ansistring=''); |
67 |
|
end; |
68 |
|
|
69 |
|
Tfb_get_master_interface = function: IMaster; |
83 |
|
when this class is freed and last reference to IStatus |
84 |
|
goes out of scope.} |
85 |
|
procedure CheckPlugins; |
80 |
– |
function Firebird4orLater: boolean; |
86 |
|
public |
87 |
|
constructor Create(aFBLibrary: TFBLibrary); |
88 |
|
destructor Destroy; override; |
89 |
|
|
90 |
|
function StatusIntf: Firebird.IStatus; |
91 |
< |
procedure Check4DataBaseError; |
91 |
> |
procedure Check4DataBaseError; overload; |
92 |
> |
procedure Check4DataBaseError(st: Firebird.IStatus); overload; |
93 |
|
function InErrorState: boolean; |
94 |
|
function LoadInterface: boolean; override; |
95 |
|
procedure FBShutdown; override; |
96 |
|
function GetAPI: IFirebirdAPI; override; |
97 |
+ |
function Firebird4orLater: boolean; |
98 |
|
{$IFDEF UNIX} |
99 |
|
function GetFirebirdLibList: string; override; |
100 |
|
{$ENDIF} |
139 |
|
function GetIMasterIntf: Firebird.IMaster; |
140 |
|
|
141 |
|
{Encode/Decode} |
135 |
– |
function DecodeInteger(bufptr: PByte; len: short): integer; override; |
142 |
|
procedure SQLEncodeDate(aDate: TDateTime; bufptr: PByte); override; |
143 |
|
function SQLDecodeDate(bufptr: PByte): TDateTime; override; |
144 |
|
procedure SQLEncodeTime(aTime: TDateTime; bufptr: PByte); override; |
146 |
|
procedure SQLEncodeDateTime(aDateTime: TDateTime; bufptr: PByte); override; |
147 |
|
function SQLDecodeDateTime(bufptr: PByte): TDateTime; override; |
148 |
|
function FormatStatus(Status: TFBStatus): AnsiString; override; |
149 |
+ |
function FormatFBStatus(Status: Firebird.IStatus): AnsiString; |
150 |
|
|
151 |
|
{Firebird 4 Extensions} |
152 |
|
procedure SQLDecFloatEncode(aValue: tBCD; SQLType: cardinal; bufptr: PByte); |
162 |
|
|
163 |
|
end; |
164 |
|
|
165 |
+ |
{ TXPBParameterBlock } |
166 |
+ |
|
167 |
+ |
TXPBParameterBlock = class(TFBInterfacedObject) |
168 |
+ |
private |
169 |
+ |
FBuilder: Firebird.IXpbBuilder; |
170 |
+ |
FFirebird30ClientAPI: TFB30ClientAPI; |
171 |
+ |
public |
172 |
+ |
constructor Create(api: TFB30ClientAPI; kind: cardinal); |
173 |
+ |
destructor Destroy; override; |
174 |
+ |
function getBuffer: PByte; |
175 |
+ |
function getDataLength: cardinal; |
176 |
+ |
procedure insertInt(tag: Byte; value: Integer); |
177 |
+ |
property Builder: Firebird.IXpbBuilder read FBuilder; |
178 |
+ |
public |
179 |
+ |
procedure PrintBuf; |
180 |
+ |
end; |
181 |
+ |
|
182 |
|
implementation |
183 |
|
|
184 |
|
uses FB30Attachment, {$IFDEF FPC}dynlibs{$ELSE} windows{$ENDIF}, |
189 |
|
PISC_DATE = ^ISC_DATE; |
190 |
|
PISC_TIME = ^ISC_TIME; |
191 |
|
|
192 |
+ |
{ TXPBParameterBlock } |
193 |
+ |
|
194 |
+ |
constructor TXPBParameterBlock.Create(api: TFB30ClientAPI; kind: cardinal); |
195 |
+ |
begin |
196 |
+ |
inherited Create; |
197 |
+ |
FFirebird30ClientAPI := api; |
198 |
+ |
with FFirebird30ClientAPI do |
199 |
+ |
begin |
200 |
+ |
FBuilder := UtilIntf.getXpbBuilder(StatusIntf,kind,nil,0); |
201 |
+ |
Check4DataBaseError; |
202 |
+ |
end; |
203 |
+ |
end; |
204 |
+ |
|
205 |
+ |
destructor TXPBParameterBlock.Destroy; |
206 |
+ |
begin |
207 |
+ |
if FBuilder <> nil then |
208 |
+ |
begin |
209 |
+ |
FBuilder.dispose; |
210 |
+ |
FBuilder := nil; |
211 |
+ |
end; |
212 |
+ |
inherited Destroy; |
213 |
+ |
end; |
214 |
+ |
|
215 |
+ |
function TXPBParameterBlock.getBuffer: PByte; |
216 |
+ |
begin |
217 |
+ |
with FFirebird30ClientAPI do |
218 |
+ |
begin |
219 |
+ |
Result := PByte(FBuilder.getBuffer(StatusIntf)); |
220 |
+ |
Check4DataBaseError; |
221 |
+ |
end; |
222 |
+ |
end; |
223 |
+ |
|
224 |
+ |
function TXPBParameterBlock.getDataLength: cardinal; |
225 |
+ |
begin |
226 |
+ |
with FFirebird30ClientAPI do |
227 |
+ |
begin |
228 |
+ |
Result := FBuilder.getBufferLength(StatusIntf); |
229 |
+ |
Check4DataBaseError; |
230 |
+ |
end; |
231 |
+ |
end; |
232 |
+ |
|
233 |
+ |
procedure TXPBParameterBlock.insertInt(tag: Byte; value: Integer); |
234 |
+ |
begin |
235 |
+ |
with FFirebird30ClientAPI do |
236 |
+ |
begin |
237 |
+ |
Builder.insertInt(StatusIntf,tag,value); |
238 |
+ |
Check4DataBaseError; |
239 |
+ |
end; |
240 |
+ |
end; |
241 |
+ |
|
242 |
+ |
procedure TXPBParameterBlock.PrintBuf; |
243 |
+ |
var i: integer; |
244 |
+ |
buffer: PByte; |
245 |
+ |
begin |
246 |
+ |
write(ClassName,': (',getDataLength,') '); |
247 |
+ |
buffer := getBuffer; |
248 |
+ |
for i := 0 to getDataLength - 1 do |
249 |
+ |
begin |
250 |
+ |
write(Format('%x ',[buffer^])); |
251 |
+ |
Inc(buffer); |
252 |
+ |
end; |
253 |
+ |
writeln |
254 |
+ |
end; |
255 |
+ |
|
256 |
|
{ TFB30StatusObject } |
257 |
|
|
258 |
|
constructor TFB30StatusObject.Create(aOwner: TFBClientAPI; |
259 |
< |
status: Firebird.IStatus); |
259 |
> |
status: Firebird.IStatus; prefix: Ansistring); |
260 |
|
begin |
261 |
< |
inherited Create(aOwner); |
261 |
> |
inherited Create(aOwner,prefix); |
262 |
|
FStatus := status; |
263 |
|
end; |
264 |
|
|
265 |
|
{ TFB30Status } |
266 |
|
|
267 |
+ |
destructor TFB30Status.Destroy; |
268 |
+ |
begin |
269 |
+ |
FreeHandle; |
270 |
+ |
inherited Destroy; |
271 |
+ |
end; |
272 |
+ |
|
273 |
|
procedure TFB30Status.Init; |
274 |
|
begin |
275 |
< |
if assigned(FStatus) then |
275 |
> |
if assigned(FStatus) and Dirty then |
276 |
> |
begin |
277 |
|
FStatus.Init; |
278 |
+ |
FDirty := false; |
279 |
+ |
end; |
280 |
+ |
end; |
281 |
+ |
|
282 |
+ |
procedure TFB30Status.FreeHandle; |
283 |
+ |
begin |
284 |
+ |
if FStatus <> nil then |
285 |
+ |
begin |
286 |
+ |
FStatus.dispose; |
287 |
+ |
FStatus := nil; |
288 |
+ |
end; |
289 |
|
end; |
290 |
|
|
291 |
|
function TFB30Status.InErrorState: boolean; |
292 |
|
begin |
293 |
|
with GetStatus do |
294 |
|
Result := ((getState and STATE_ERRORS) <> 0); |
295 |
+ |
if Result then |
296 |
+ |
FDirty := true; |
297 |
+ |
end; |
298 |
+ |
|
299 |
+ |
function TFB30Status.Warning: boolean; |
300 |
+ |
begin |
301 |
+ |
with GetStatus do |
302 |
+ |
Result := ((getState and STATE_WARNINGS) <> 0); |
303 |
+ |
if Result then |
304 |
+ |
FDirty := true; |
305 |
|
end; |
306 |
|
|
307 |
|
function TFB30Status.GetStatus: Firebird.IStatus; |
308 |
|
begin |
309 |
|
if FStatus = nil then |
310 |
< |
with FOwner do |
311 |
< |
FStatus := (FOwner as TFB30ClientAPI).MasterIntf.GetStatus; |
310 |
> |
with FOwner do |
311 |
> |
FStatus := (FOwner as TFB30ClientAPI).MasterIntf.GetStatus; |
312 |
|
Result := FStatus; |
313 |
|
end; |
314 |
|
|
345 |
|
|
346 |
|
function TFB30ClientAPI.Firebird4orLater: boolean; |
347 |
|
begin |
348 |
< |
Result := (GetClientMajor >=4) and (UtilIntf.vtable.version >= 4) |
348 |
> |
Result := (GetClientMajor > 4) or ( |
349 |
> |
(GetClientMajor = 4) and (UtilIntf.vtable.version >= 4) |
350 |
|
and (UtilIntf.vtable.version <> 21) {ignore FB4 Beta1} |
351 |
< |
and (UtilIntf.vtable.version <> 24) {ignore FB4 Beta2} |
351 |
> |
and (UtilIntf.vtable.version <> 24)) {ignore FB4 Beta2} |
352 |
|
end; |
353 |
|
|
354 |
|
{$IFDEF UNIX} |
377 |
|
|
378 |
|
procedure TFB30ClientAPI.FBShutdown; |
379 |
|
begin |
380 |
< |
if assigned(fb_shutdown) and assigned(FProvider) then |
380 |
> |
if assigned(fb_shutdown) then |
381 |
|
begin |
382 |
< |
FProvider.release; |
383 |
< |
FProvider := nil; |
382 |
> |
FStatus.FreeHandle; |
383 |
> |
if assigned(FProvider) then |
384 |
> |
begin |
385 |
> |
FProvider.release; |
386 |
> |
FProvider := nil; |
387 |
> |
end; |
388 |
|
end; |
389 |
|
inherited; |
390 |
|
end; |
403 |
|
|
404 |
|
destructor TFB30ClientAPI.Destroy; |
405 |
|
begin |
406 |
+ |
FStatus.FreeHandle; |
407 |
|
if assigned(FProvider) then |
408 |
|
FProvider.release; |
409 |
|
inherited Destroy; |
421 |
|
IBDataBaseError; |
422 |
|
end; |
423 |
|
|
424 |
+ |
procedure TFB30ClientAPI.Check4DataBaseError(st: Firebird.IStatus); |
425 |
+ |
begin |
426 |
+ |
if ((st.getState and st.STATE_ERRORS) <> 0) then |
427 |
+ |
raise EIBInterBaseError.Create(TFB30StatusObject.Create(self,st)); |
428 |
+ |
end; |
429 |
+ |
|
430 |
|
function TFB30ClientAPI.InErrorState: boolean; |
431 |
|
begin |
432 |
|
Result := FStatus.InErrorState; |
540 |
|
Result := UtilIntf.GetClientVersion mod 256; |
541 |
|
end; |
542 |
|
|
415 |
– |
function TFB30ClientAPI.DecodeInteger(bufptr: PByte; len: short): integer; |
416 |
– |
var P: PByte; |
417 |
– |
begin |
418 |
– |
Result := 0; |
419 |
– |
P := Bufptr + len - 1; |
420 |
– |
while P >= bufptr do |
421 |
– |
begin |
422 |
– |
Result := (Result shl 8 ) or P^; |
423 |
– |
Dec(P); |
424 |
– |
end; |
425 |
– |
end; |
426 |
– |
|
543 |
|
procedure TFB30ClientAPI.SQLEncodeDate(aDate: TDateTime; bufptr: PByte); |
544 |
|
var |
545 |
|
Yr, Mn, Dy: Word; |
600 |
|
end; |
601 |
|
|
602 |
|
function TFB30ClientAPI.FormatStatus(Status: TFBStatus): AnsiString; |
603 |
+ |
begin |
604 |
+ |
Result := FormatFBStatus((Status as TFB30Status).GetStatus); |
605 |
+ |
end; |
606 |
+ |
|
607 |
+ |
function TFB30ClientAPI.FormatFBStatus(Status: Firebird.IStatus): AnsiString; |
608 |
|
var local_buffer: array[0..IBHugeLocalBufferLength - 1] of AnsiChar; |
609 |
|
begin |
610 |
|
Result := ''; |
611 |
< |
if UtilIntf.formatStatus(@local_buffer,sizeof(local_buffer),(Status as TFB30Status).GetStatus) > 0 then |
611 |
> |
if UtilIntf.formatStatus(@local_buffer,sizeof(local_buffer) - 1,Status) > 0 then |
612 |
|
Result := strpas(local_buffer); |
613 |
|
end; |
614 |
|
|