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