ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/udr/client/3.0/FB30Attachment.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: 16430 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 FB30Attachment;
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, FBAttachment, FBClientAPI, FB30ClientAPI, Firebird, IB,
41 FBActivityMonitor, FBParamBlock;
42
43 type
44
45 { TFB30Attachment }
46
47 TFB30Attachment = class(TFBAttachment,IAttachment, IActivityMonitor)
48 private
49 FAttachmentIntf: Firebird.IAttachment;
50 FFirebird30ClientAPI: TFB30ClientAPI;
51 FTimeZoneServices: ITimeZoneServices;
52 FUsingRemoteICU: boolean;
53 FOwnsAttachmentHandle: boolean;
54 procedure SetAttachmentIntf(AValue: Firebird.IAttachment);
55 procedure SetUseRemoteICU(aValue: boolean);
56 protected
57 procedure CheckHandle; override;
58 function GetAttachment: IAttachment; override;
59 public
60 constructor Create(api: TFB30ClientAPI; DatabaseName: AnsiString; aDPB: IDPB;
61 RaiseExceptionOnConnectError: boolean); overload;
62 constructor Create(api: TFB30ClientAPI;
63 attachment: Firebird.IAttachment; aDatabaseName: AnsiString); overload;
64 constructor CreateDatabase(api: TFB30ClientAPI; DatabaseName: AnsiString; aDPB: IDPB; RaiseExceptionOnError: boolean); overload;
65 constructor CreateDatabase(api: TFB30ClientAPI; sql: AnsiString; aSQLDialect: integer;
66 RaiseExceptionOnError: boolean); overload;
67 function GetDBInfo(ReqBuffer: PByte; ReqBufLen: integer): IDBInformation;
68 override;
69 property AttachmentIntf: Firebird.IAttachment read FAttachmentIntf write SetAttachmentIntf;
70 property Firebird30ClientAPI: TFB30ClientAPI read FFirebird30ClientAPI;
71
72 public
73 {IAttachment}
74 procedure Connect;
75 procedure Disconnect(Force: boolean=false); override;
76 function IsConnected: boolean; override;
77 procedure DropDatabase;
78 function StartTransaction(TPB: array of byte; DefaultCompletion: TTransactionCompletion; aName: AnsiString=''): ITransaction; override;
79 function StartTransaction(TPB: ITPB; DefaultCompletion: TTransactionCompletion; aName: AnsiString=''): ITransaction; override;
80 procedure ExecImmediate(transaction: ITransaction; sql: AnsiString; aSQLDialect: integer); override;
81 function Prepare(transaction: ITransaction; sql: AnsiString; aSQLDialect: integer; CursorName: AnsiString=''): IStatement; override;
82 function PrepareWithNamedParameters(transaction: ITransaction; sql: AnsiString;
83 aSQLDialect: integer; GenerateParamNames: boolean=false;
84 CaseSensitiveParams: boolean=false; CursorName: AnsiString=''): IStatement; override;
85
86 {Events}
87 function GetEventHandler(Events: TStrings): IEvents; override;
88
89 {Blob - may use to open existing Blobs. However, ISQLData.AsBlob is preferred}
90
91 function CreateBlob(transaction: ITransaction; BlobMetaData: IBlobMetaData; BPB: IBPB=nil): IBlob; overload; override;
92 function CreateBlob(transaction: ITransaction; SubType: integer; aCharSetID: cardinal=0; BPB: IBPB=nil): IBlob; overload;
93 function OpenBlob(transaction: ITransaction; BlobMetaData: IBlobMetaData; BlobID: TISC_QUAD; BPB: IBPB=nil): IBlob; overload; override;
94
95 {Array}
96 function OpenArray(transaction: ITransaction; ArrayMetaData: IArrayMetaData; ArrayID: TISC_QUAD): IArray; overload; override;
97 function CreateArray(transaction: ITransaction; ArrayMetaData: IArrayMetaData): IArray; overload; override;
98 function CreateArrayMetaData(SQLType: cardinal; tableName: AnsiString;
99 columnName: AnsiString; Scale: integer; size: cardinal; aCharSetID: cardinal;
100 dimensions: cardinal; bounds: TArrayBounds): IArrayMetaData;
101
102
103 {Database Information}
104 function GetBlobMetaData(Transaction: ITransaction; tableName, columnName: AnsiString): IBlobMetaData; override;
105 function GetArrayMetaData(Transaction: ITransaction; tableName, columnName: AnsiString): IArrayMetaData; override;
106 procedure getFBVersion(version: TStrings);
107 function HasDecFloatSupport: boolean; override;
108 function HasBatchMode: boolean; override;
109 function HasScollableCursors: boolean;
110
111 {Time Zone Support}
112 function GetTimeZoneServices: ITimeZoneServices; override;
113 function HasTimeZoneSupport: boolean; override;
114 end;
115
116 implementation
117
118 uses FB30Transaction, FB30Statement, FB30Array, FB30Blob, FBMessages,
119 FBOutputBlock, FB30Events, IBUtils, FB30TimeZoneServices;
120
121 type
122 { TVersionCallback }
123
124 TVersionCallback = class(Firebird.IVersionCallbackImpl)
125 private
126 FOutput: TStrings;
127 FFirebirdClientAPI: TFBClientAPI;
128 public
129 constructor Create(FirebirdClientAPI: TFBClientAPI; output: TStrings);
130 procedure callback(status: Firebird.IStatus; text: PAnsiChar); override;
131 end;
132
133 { TVersionCallback }
134
135 constructor TVersionCallback.Create(FirebirdClientAPI: TFBClientAPI;
136 output: TStrings);
137 begin
138 inherited Create;
139 FFirebirdClientAPI := FirebirdClientAPI;
140 FOutput := output;
141 end;
142
143 procedure TVersionCallback.callback(status: Firebird.IStatus; text: PAnsiChar);
144 var StatusObj: TFB30StatusObject;
145 begin
146 if ((status.getState and status.STATE_ERRORS) <> 0) then
147 begin
148 StatusObj := TFB30StatusObject.Create(FFirebirdClientAPI,status);
149 try
150 raise EIBInterBaseError.Create(StatusObj);
151 finally
152 StatusObj.Free;
153 end;
154 end;
155 FOutput.Add(text);
156 end;
157
158
159 { TFB30Attachment }
160
161 procedure TFB30Attachment.SetUseRemoteICU(aValue: boolean);
162 begin
163 if (FUsingRemoteICU <> aValue) and (GetODSMajorVersion >= 13) then
164 begin
165 if aValue then
166 ExecImmediate([isc_tpb_write,isc_tpb_wait,isc_tpb_concurrency],'SET BIND OF TIME ZONE TO EXTENDED')
167 else
168 ExecImmediate([isc_tpb_write,isc_tpb_wait,isc_tpb_concurrency],'SET BIND OF TIME ZONE TO NATIVE');
169 FUsingRemoteICU := aValue;
170 end;
171 end;
172
173 procedure TFB30Attachment.SetAttachmentIntf(AValue: Firebird.IAttachment);
174 begin
175 if FAttachmentIntf = AValue then Exit;
176 if FAttachmentIntf <> nil then
177 try
178 FAttachmentIntf.release;
179 except {ignore - forced release}
180 end;
181 FOwnsAttachmentHandle := false;
182 ClearCachedInfo;
183 FTimeZoneServices := nil;
184 FAttachmentIntf := AValue;
185 if FAttachmentIntf <> nil then
186 FAttachmentIntf.AddRef;
187 end;
188
189 procedure TFB30Attachment.CheckHandle;
190 begin
191 if FAttachmentIntf = nil then
192 IBError(ibxeDatabaseClosed,[nil]);
193 end;
194
195 function TFB30Attachment.GetAttachment: IAttachment;
196 begin
197 Result := self;
198 end;
199
200 constructor TFB30Attachment.Create(api: TFB30ClientAPI; DatabaseName: AnsiString; aDPB: IDPB;
201 RaiseExceptionOnConnectError: boolean);
202 begin
203 FFirebird30ClientAPI := api;
204 if aDPB = nil then
205 begin
206 if RaiseExceptionOnConnectError then
207 IBError(ibxeNoDPB,[nil]);
208 Exit;
209 end;
210 inherited Create(api,DatabaseName,aDPB,RaiseExceptionOnConnectError);
211 Connect;
212 end;
213
214 constructor TFB30Attachment.CreateDatabase(api: TFB30ClientAPI; DatabaseName: AnsiString; aDPB: IDPB;
215 RaiseExceptionOnError: boolean);
216 var Param: IDPBItem;
217 sql: AnsiString;
218 IsCreateDB: boolean;
219 Intf: Firebird.IAttachment;
220 begin
221 inherited Create(api,DatabaseName,aDPB,RaiseExceptionOnError);
222 FFirebird30ClientAPI := api;
223 IsCreateDB := true;
224 if aDPB <> nil then
225 begin
226 Param := aDPB.Find(isc_dpb_set_db_SQL_dialect);
227 if Param <> nil then
228 SetSQLDialect(Param.AsByte);
229 end;
230 sql := GenerateCreateDatabaseSQL(DatabaseName,aDPB);
231 with FFirebird30ClientAPI do
232 begin
233 Intf := UtilIntf.executeCreateDatabase(StatusIntf,Length(sql),
234 PAnsiChar(sql),SQLDialect,@IsCreateDB);
235 if FRaiseExceptionOnConnectError then Check4DataBaseError;
236 if not InErrorState then
237 begin
238 if aDPB <> nil then
239 {Connect using known parameters}
240 begin
241 Intf.Detach(StatusIntf); {releases interface}
242 Check4DataBaseError;
243 Connect;
244 end
245 else
246 AttachmentIntf := Intf;
247 FOwnsAttachmentHandle:= true;
248 end;
249 end;
250 end;
251
252 constructor TFB30Attachment.CreateDatabase(api: TFB30ClientAPI; sql: AnsiString; aSQLDialect: integer;
253 RaiseExceptionOnError: boolean);
254 var IsCreateDB: boolean;
255 Intf: Firebird.IAttachment;
256 begin
257 inherited Create(api,'',nil,RaiseExceptionOnError);
258 FFirebird30ClientAPI := api;
259 SetSQLDialect(aSQLDialect);
260 with FFirebird30ClientAPI do
261 begin
262 Intf := UtilIntf.executeCreateDatabase(StatusIntf,Length(sql),
263 PAnsiChar(sql),aSQLDialect,@IsCreateDB);
264 if FRaiseExceptionOnConnectError then Check4DataBaseError;
265 if InErrorState then
266 Exit;
267 end;
268 AttachmentIntf := Intf;
269 FOwnsAttachmentHandle:= true;
270 ExtractConnectString(sql,FDatabaseName);
271 DPBFromCreateSQL(sql);
272 end;
273
274 constructor TFB30Attachment.Create(api: TFB30ClientAPI;
275 attachment: Firebird.IAttachment; aDatabaseName: AnsiString);
276 begin
277 inherited Create(api,aDatabaseName,nil,false);
278 FFirebird30ClientAPI := api;
279 AttachmentIntf := attachment;
280 end;
281
282 function TFB30Attachment.GetDBInfo(ReqBuffer: PByte; ReqBufLen: integer): IDBInformation;
283 begin
284 Result := TDBInformation.Create(Firebird30ClientAPI);
285 with FFirebird30ClientAPI, Result as TDBInformation do
286 begin
287 FAttachmentIntf.getInfo(StatusIntf, ReqBufLen, BytePtr(ReqBuffer),
288 getBufSize, BytePtr(Buffer));
289 Check4DataBaseError;
290 end
291 end;
292
293 procedure TFB30Attachment.Connect;
294 var Intf: Firebird.IAttachment;
295 begin
296 with FFirebird30ClientAPI do
297 begin
298 Intf := ProviderIntf.attachDatabase(StatusIntf,PAnsiChar(FDatabaseName),
299 (DPB as TDPB).getDataLength,
300 BytePtr((DPB as TDPB).getBuffer));
301 if FRaiseExceptionOnConnectError then Check4DataBaseError;
302 if not InErrorState then
303 begin
304 AttachmentIntf := Intf;
305 FOwnsAttachmentHandle := true;
306 end;
307 end;
308 end;
309
310 procedure TFB30Attachment.Disconnect(Force: boolean);
311 begin
312 inherited Disconnect(Force);
313 if IsConnected then
314 begin
315 if FOwnsAttachmentHandle then
316 with FFirebird30ClientAPI do
317 begin
318 EndAllTransactions;
319 FAttachmentIntf.Detach(StatusIntf);
320 if not Force and InErrorState then
321 IBDataBaseError;
322 end;
323 AttachmentIntf := nil;
324 end;
325 end;
326
327 function TFB30Attachment.IsConnected: boolean;
328 begin
329 Result := FAttachmentIntf <> nil;
330 end;
331
332 procedure TFB30Attachment.DropDatabase;
333 begin
334 if IsConnected then
335 begin
336 if not FOwnsAttachmentHandle then
337 IBError(ibxeCantDropAcquiredDB,[nil]);
338 with FFirebird30ClientAPI do
339 begin
340 EndAllTransactions;
341 EndSession(false);
342 FAttachmentIntf.dropDatabase(StatusIntf);
343 Check4DataBaseError;
344 end;
345 AttachmentIntf := nil;
346 end;
347 end;
348
349 function TFB30Attachment.StartTransaction(TPB: array of byte;
350 DefaultCompletion: TTransactionCompletion; aName: AnsiString): ITransaction;
351 begin
352 CheckHandle;
353 Result := TFB30Transaction.Create(FFirebird30ClientAPI,self,TPB,DefaultCompletion, aName);
354 end;
355
356 function TFB30Attachment.StartTransaction(TPB: ITPB;
357 DefaultCompletion: TTransactionCompletion; aName: AnsiString): ITransaction;
358 begin
359 CheckHandle;
360 Result := TFB30Transaction.Create(FFirebird30ClientAPI,self,TPB,DefaultCompletion,aName);
361 end;
362
363 procedure TFB30Attachment.ExecImmediate(transaction: ITransaction; sql: AnsiString;
364 aSQLDialect: integer);
365 begin
366 CheckHandle;
367 with FFirebird30ClientAPI do
368 begin
369 FAttachmentIntf.execute(StatusIntf,(transaction as TFB30Transaction).TransactionIntf,
370 Length(sql),PAnsiChar(sql),aSQLDialect,nil,nil,nil,nil);
371 Check4DataBaseError;
372 end;
373 end;
374
375 function TFB30Attachment.Prepare(transaction: ITransaction; sql: AnsiString;
376 aSQLDialect: integer; CursorName: AnsiString): IStatement;
377 begin
378 CheckHandle;
379 Result := TFB30Statement.Create(self,transaction,sql,aSQLDialect,CursorName);
380 end;
381
382 function TFB30Attachment.PrepareWithNamedParameters(transaction: ITransaction;
383 sql: AnsiString; aSQLDialect: integer; GenerateParamNames: boolean;
384 CaseSensitiveParams: boolean; CursorName: AnsiString): IStatement;
385 begin
386 CheckHandle;
387 Result := TFB30Statement.CreateWithParameterNames(self,transaction,sql,aSQLDialect,
388 GenerateParamNames,CaseSensitiveParams,CursorName);
389 end;
390
391 function TFB30Attachment.GetEventHandler(Events: TStrings): IEvents;
392 begin
393 CheckHandle;
394 Result := TFB30Events.Create(self,Events);
395 end;
396
397 function TFB30Attachment.CreateBlob(transaction: ITransaction;
398 BlobMetaData: IBlobMetaData; BPB: IBPB): IBlob;
399 begin
400 CheckHandle;
401 Result := TFB30Blob.Create(self,transaction as TFB30Transaction, BlobMetaData,BPB);
402 end;
403
404 function TFB30Attachment.CreateBlob(transaction: ITransaction;
405 SubType: integer; aCharSetID: cardinal; BPB: IBPB): IBlob;
406 begin
407 CheckHandle;
408 Result := TFB30Blob.Create(self,transaction as TFB30Transaction, SubType,aCharSetID,BPB);
409 end;
410
411 function TFB30Attachment.OpenBlob(transaction: ITransaction;
412 BlobMetaData: IBlobMetaData; BlobID: TISC_QUAD; BPB: IBPB): IBlob;
413 begin
414 CheckHandle;
415 Result := TFB30Blob.Create(self,transaction as TFB30transaction,BlobMetaData,BlobID,BPB);
416 end;
417
418 function TFB30Attachment.OpenArray(transaction: ITransaction;
419 ArrayMetaData: IArrayMetaData; ArrayID: TISC_QUAD): IArray;
420 begin
421 CheckHandle;
422 Result := TFB30Array.Create(self,transaction as TFB30Transaction,
423 ArrayMetaData,ArrayID);
424 end;
425
426 function TFB30Attachment.CreateArray(transaction: ITransaction;
427 ArrayMetaData: IArrayMetaData): IArray;
428 begin
429 CheckHandle;
430 Result := TFB30Array.Create(self,transaction as TFB30Transaction,ArrayMetaData);
431 end;
432
433 function TFB30Attachment.CreateArrayMetaData(SQLType: cardinal; tableName: AnsiString; columnName: AnsiString;
434 Scale: integer; size: cardinal; aCharSetID: cardinal; dimensions: cardinal;
435 bounds: TArrayBounds): IArrayMetaData;
436 begin
437 Result := TFB30ArrayMetaData.Create(self,SQLType,tableName,ColumnName,Scale,size,aCharSetID, dimensions,bounds);
438 end;
439
440 function TFB30Attachment.GetBlobMetaData(Transaction: ITransaction; tableName,
441 columnName: AnsiString): IBlobMetaData;
442 begin
443 CheckHandle;
444 Result := TFB30BlobMetaData.Create(self,Transaction as TFB30Transaction,tableName,columnName);
445 end;
446
447 function TFB30Attachment.GetArrayMetaData(Transaction: ITransaction; tableName,
448 columnName: AnsiString): IArrayMetaData;
449 begin
450 CheckHandle;
451 Result := TFB30ArrayMetaData.Create(self,Transaction as TFB30Transaction,tableName,columnName);
452 end;
453
454 procedure TFB30Attachment.getFBVersion(version: TStrings);
455 var bufferObj: TVersionCallback;
456 begin
457 version.Clear;
458 bufferObj := TVersionCallback.Create(Firebird30ClientAPI,version);
459 try
460 with FFirebird30ClientAPI do
461 begin
462 UtilIntf.getFbVersion(StatusIntf,FAttachmentIntf,bufferObj);
463 Check4DataBaseError;
464 end;
465 finally
466 bufferObj.Free;
467 end;
468 end;
469
470 function TFB30Attachment.HasDecFloatSupport: boolean;
471 begin
472 Result := (FFirebird30ClientAPI.GetClientMajor >= 4) and
473 (GetODSMajorVersion >= 13);
474 end;
475
476 function TFB30Attachment.HasBatchMode: boolean;
477 begin
478 Result := FFirebird30ClientAPI.Firebird4orLater and
479 (GetODSMajorVersion >= 13);
480 end;
481
482 function TFB30Attachment.HasScollableCursors: boolean;
483 begin
484 Result := (GetODSMajorVersion >= 12);
485 end;
486
487 function TFB30Attachment.GetTimeZoneServices: ITimeZoneServices;
488 begin
489 if not HasTimeZoneSupport then
490 IBError(ibxeNotSupported,[]);
491
492 if FTimeZoneServices = nil then
493 FTimeZoneServices := TFB30TimeZoneServices.Create(self);
494 Result := FTimeZoneServices;
495 end;
496
497 function TFB30Attachment.HasTimeZoneSupport: boolean;
498 begin
499 Result := (FFirebird30ClientAPI.GetClientMajor >= 4) and
500 (GetODSMajorVersion >= 13);
501 end;
502
503 end.
504

Properties

Name Value
svn:eol-style native