ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/fbintf/client/3.0/FB30Attachment.pas
Revision: 345
Committed: Mon Aug 23 14:22:29 2021 UTC (3 years, 3 months ago) by tony
Content type: text/x-pascal
File size: 14914 byte(s)
Log Message:
Merged into public release

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