ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/iblocaldb/IBXCustomIBLocalDBSupport.pas
Revision: 45
Committed: Tue Dec 6 10:33:46 2016 UTC (7 years, 11 months ago) by tony
Content type: text/x-pascal
File size: 20882 byte(s)
Log Message:
Committing updates for Release R2-0-0

File Contents

# Content
1 (*
2 * IBX For Lazarus (Firebird Express)
3 *
4 * The contents of this file are subject to the Initial Developer's
5 * Public License Version 1.0 (the "License"); you may not use this
6 * file except in compliance with the License. You may obtain a copy
7 * of the License here:
8 *
9 * http://www.firebirdsql.org/index.php?op=doc&id=idpl
10 *
11 * Software distributed under the License is distributed on an "AS
12 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
13 * implied. See the License for the specific language governing rights
14 * and limitations under the License.
15 *
16 * The Initial Developer of the Original Code is Tony Whyman.
17 *
18 * The Original Code is (C) 2014 Tony Whyman, MWA Software
19 * (http://www.mwasoftware.co.uk).
20 *
21 * All Rights Reserved.
22 *
23 * Contributor(s): ______________________________________.
24 *
25 *)
26 unit IBXCustomIBLocalDBSupport;
27
28 {$mode objfpc}{$H+}
29
30 interface
31
32 uses
33 Classes, IBDatabase, SysUtils, IBServices, IBXUpgradeConfFile, ibxscript,
34 IB;
35
36 type
37
38 { TCustomIBLocalDBSupport Properties
39
40 * Database: reference to the TIBDatabase component for the local database
41 * DatabaseName: filename (no path) to use for the Firebird Database file.
42 * EmptyDBArchive: filename (optional path) holding the database initialisation archive.
43 May either be absolute path or relative to shared data directory.
44 * Enabled: when false component does nothing
45 * FirebirdDirectory: Full path to directory holding firebird.conf. May either be
46 absolute path or relative to the shared data directory. If empty, defaults to shared data directory.
47 * Name: Component Name
48 * Options:
49 iblAutoUpgrade: Automatically apply upgrade when database schema
50 version is lower than required.
51 IblAllowDowngrade: Automatically apply downgrade when available to
52 schema version compatible with the required version.
53 iblQuiet: true then no database overwrite warnings
54 * RequiredVersionNo: The schema version number required by the application.
55 TIBLocalDBSupport will normally try to upgrade/downgrade the schema to satisfy
56 this requirement.
57 * UpgradeConfFile: Path to upgrade configuration file. May either be absolute
58 path or relative to the shared data directory.
59 * VendorName: Used to construct path to Database Directory.
60
61 Note that at design time paths may use '/' or '\' as directory separator. At
62 run time, they must be specified using the appropriate Directory Separator
63 for the current platform.
64
65 Events:
66
67 * OnGetDatabaseName: The database name is normally computed automatically.
68 However, this event allows an application to inspect and override the result.
69 * OnNewDatabaseOpen: called after the successful initialisation of an empty local database.
70 * OnGetDBVersionNo: called to get the current database schema version number.
71 If this event is not handled then schema upgrade/downgrade is never performed.
72 * OnGetSharedDataDir: The shared data directory is normally computed automatically.
73 However, this event allows an application to inspect and override the result.
74 }
75
76 TOnGetDatabaseName = procedure(Sender: TObject; var DBName: string) of object;
77 TOnGetDBVersionNo = procedure (Sender: TObject; var VersionNo: integer) of object;
78 TOnGetSharedDataDir = procedure(Sender: TObject; var SharedDataDir: string) of object;
79
80 TIBLocalOption = (iblAutoUpgrade, iblAllowDowngrade, iblQuiet);
81 TIBLocalOptions = set of TIBLocalOption;
82
83
84 { TCustomIBLocalDBSupport }
85
86 TCustomIBLocalDBSupport = class(TComponent)
87 private
88 { Private declarations }
89 FActiveDatabasePathName: string;
90 FCurrentDBVersionNo: integer;
91 FEmptyDBArchive: string;
92 FEnabled: boolean;
93 FFirebirdDirectory: string;
94 FIBBase: TIBBase;
95 FDatabaseName: string;
96 FOnGetDatabaseName: TOnGetDatabaseName;
97 FOnGetDBVersionNo: TOnGetDBVersionNo;
98 FOnGetSharedDataDir: TOnGetSharedDataDir;
99 FOnNewDatabaseOpen: TNotifyEvent;
100 FOptions: TIBLocalOptions;
101 FRequiredVersionNo: integer;
102 FUpgradeConfFile: string;
103 FNewDBCreated: boolean;
104 FVendorName: string;
105 FInUpgrade: boolean;
106 FDownGradeArchive: string;
107 FSharedDataDir: string;
108 FUpgradeConf: TUpgradeConfFile;
109 procedure CheckEnabled;
110 procedure CreateDatabase(DBName: string; DBParams: TStrings; Overwrite: boolean);
111 function GetDatabase: TIBDatabase;
112 procedure SetDatabase(AValue: TIBDatabase);
113 function GetDBNameAndPath: string;
114 procedure InitDatabaseParameters(DBParams: TStrings;
115 var DBName: string);
116 function MapSharedDataDir(aDataDir: string): string;
117 procedure OnBeforeDatabaseConnect(Sender: TObject; DBParams: TStrings;
118 var DBName: string);
119 procedure OnDatabaseConnect(Sender: TObject);
120 procedure OnAfterDatabaseDisconnect(Sender: TObject);
121 procedure PrepareDBParams(DBParams: TStrings);
122 procedure SetDatabaseName(AValue: string);
123 procedure SetFirebirdDirectory(AValue: string);
124 procedure SetupFirebirdEnv;
125 procedure UpgradeCheck;
126 protected
127 { Protected declarations }
128 function AllowInitialisation: boolean; virtual;
129 function AllowRestore: boolean; virtual;
130 procedure CreateDir(DirName: string);
131 function CreateNewDatabase(DBName:string; DBParams: TStrings; DBArchive: string): boolean; virtual; abstract;
132 procedure HandleGetParamValue(Sender: TObject; ParamName: string; var BlobID: TISC_QUAD);
133 procedure Downgrade(DBArchive: string); virtual;
134 procedure DowngradeDone;
135 procedure Loaded; override;
136 function RestoreDatabaseFromArchive(DBName:string; DBParams: TStrings; aFilename: string): boolean; virtual; abstract;
137 function RunUpgradeDatabase(TargetVersionNo: integer): boolean; virtual; abstract;
138 function SaveDatabaseToArchive(DBName: string; DBParams:TStrings; aFilename: string): boolean; virtual; abstract;
139 function UpdateVersionNo: boolean;
140 property DownGradeArchive: string read FDownGradeArchive;
141 property UpgradeConf: TUpgradeConfFile read FUpgradeConf;
142 public
143 { Public declarations }
144 constructor Create(aOwner: TComponent); override;
145 destructor Destroy; override;
146
147 function DowngradePending: boolean;
148
149 {NewDatabase: called to reinitialise the local database using the initialisation
150 archive. Overwrites existing data so use carefully.}
151 procedure NewDatabase;
152
153 {Perform a downgrade to target version if backup archive available.
154 Note: normally called from UpgradeCheck if iblAllowDowngrade in Options}
155 procedure PerformDowngrade(TargetVersionNo: integer);
156
157 {Perform schema upgrade to target version if upgrade scripts available.
158 Note: normally called from UpgradeCheck if iblAllowUpgrade in Options}
159 procedure PerformUpgrade(TargetVersionNo: integer);
160
161 {RestoreDatabase: overwrites the existing local database with the specified
162 gbak format archive. User is prompted to locate archive if filename empty.}
163 procedure RestoreDatabase (filename: string = '');
164
165 {SaveDatabase: Saves the current database into a gbak format archive. User
166 is prompted for archive filename if filename empty.}
167 procedure SaveDatabase(filename: string = '');
168
169 {Copies database parameters as give in the DBParams to the Service
170 omitting any parameters not appropriate for TIBService. Typically, the
171 DBParams are TIBDatabase.Params}
172 class procedure SetDBParams(aService: TIBCustomService; DBParams: TStrings);
173
174 property ActiveDatabasePathName: string read FActiveDatabasePathName;
175 property CurrentDBVersionNo: integer read FCurrentDBVersionNo;
176
177 { Likely to be Published declarations }
178 property Database: TIBDatabase read GetDatabase write SetDatabase;
179 property DatabaseName: string read FDatabaseName write SetDatabaseName;
180 property Enabled: boolean read FEnabled write FEnabled default true;
181 property EmptyDBArchive: string read FEmptyDBArchive write FEmptyDBArchive;
182 property FirebirdDirectory: string read FFirebirdDirectory write SetFirebirdDirectory;
183 property Options: TIBLocalOptions read FOptions write FOptions;
184 property RequiredVersionNo: integer read FRequiredVersionNo write FRequiredVersionNo;
185 property UpgradeConfFile: string read FUpgradeConfFile write FUpgradeConfFile;
186 property VendorName: string read FVendorName write FVendorName;
187 property OnGetDatabaseName: TOnGetDatabaseName read FOnGetDatabaseName write FOnGetDatabaseName;
188 property OnGetDBVersionNo: TOnGetDBVersionNo read FOnGetDBVersionNo write FOnGetDBVersionNo;
189 property OnNewDatabaseOpen: TNotifyEvent read FOnNewDatabaseOpen write FOnNewDatabaseOpen;
190 property OnGetSharedDataDir: TOnGetSharedDataDir read FOnGetSharedDataDir write FOnGetSharedDataDir;
191 end;
192
193 EIBLocalFatalError = class(Exception);
194
195 implementation
196
197 uses DB, IBBlob, ZStream
198 {$IFDEF Unix} ,initc, regexpr {$ENDIF}
199 {$IFDEF WINDOWS} ,Windows ,Windirs {$ENDIF};
200
201 resourcestring
202 sNoDowngrade = 'Database Schema is %d. Unable to downgrade to version %d';
203 sLocalDBDisabled = 'Local Database Access Disabled';
204 sEmptyDBArchiveMissing = 'Unable to create database - no empty DB archive specified';
205 sEmptyDBArchiveNotFound = 'Unable to create database - empty DB archive file not found';
206 sNoEmbeddedServer = 'Firebird Embedded Server is required but is not installed';
207
208 { TCustomIBLocalDBSupport }
209
210
211 procedure TCustomIBLocalDBSupport.HandleGetParamValue(Sender: TObject;
212 ParamName: string; var BlobID: TISC_QUAD);
213 var Blob: TIBBlobStream;
214 Source: TStream;
215 FileName: string;
216 begin
217 Blob := TIBBlobStream.Create;
218 try
219 Blob.Database := (Sender as TIBXScript).Database;
220 Blob.Transaction := (Sender as TIBXScript).Transaction;
221 Blob.Mode := bmWrite;
222 if not assigned(UpgradeConf) or
223 not UpgradeConf.GetSourceFile(ParamName,FileName) then Exit;
224
225 if CompareText(ExtractFileExt(FileName),'.gz') = 0 then {gzip compressed file}
226 Source := TGZFileStream.Create(FileName,gzopenread)
227 else
228 Source := TFileStream.Create(FileName,fmOpenRead or fmShareDenyNone);
229 try
230 Blob.CopyFrom(Source,0)
231 finally
232 Source.Free
233 end;
234 Blob.Finalize;
235 BlobID := Blob.BlobID
236 finally
237 Blob.Free
238 end
239 end;
240
241 procedure TCustomIBLocalDBSupport.CheckEnabled;
242 begin
243 if not Enabled then
244 raise Exception.Create(sLocalDBDisabled);
245 end;
246
247 procedure TCustomIBLocalDBSupport.CreateDatabase(DBName: string; DBParams: TStrings;
248 Overwrite: boolean);
249 var DBArchive: string;
250 begin
251 CheckEnabled;
252 DBArchive := EmptyDBArchive;
253 if DBArchive = '' then
254 raise Exception.Create(sEmptyDBArchiveMissing);
255
256 if not TUpgradeConfFile.IsAbsolutePath(DBArchive) then
257 DBArchive := FSharedDataDir + DBArchive;
258
259 if not FileExists(DBArchive) then
260 raise Exception.Create(sEmptyDBArchiveNotFound);
261
262 if FileExists(DBName) then
263 begin
264 if not Overwrite then Exit;
265
266 sysutils.DeleteFile(DBName);
267 end;
268
269 SetupFirebirdEnv;
270 CreateNewDatabase(DBName,DBParams,DBArchive);
271 FNewDBCreated := true;
272 end;
273
274 function TCustomIBLocalDBSupport.GetDatabase: TIBDatabase;
275 begin
276 Result := FIBBase.Database;
277 end;
278
279 procedure TCustomIBLocalDBSupport.SetDatabase(AValue: TIBDatabase);
280 begin
281 FIBBase.Database := AValue;
282 end;
283
284 function TCustomIBLocalDBSupport.MapSharedDataDir(aDataDir: string): string;
285 {$IFDEF UNIX}
286 var RegexObj: TRegExpr;
287 {$ENDIF}
288 begin
289 Result := aDataDir;
290 {$IFDEF UNIX}
291
292 {Under Unix transform application exe paths that are in installed locations
293 e.g. /usr/local/bin to corresponding shared data locations ee.g. /usr/local/shared}
294 RegexObj := TRegExpr.Create;
295 try
296 RegexObj.Expression := '^/usr(/local|)/(s|)bin/.*$';
297 if RegexObj.Exec(aDataDir) then
298 Result := '/usr' + RegexObj.Match[1] + '/share/' + ApplicationName + '/';
299 finally
300 RegexObj.Free;
301 end;
302 {$ENDIF}
303 if assigned (OnGetSharedDataDir) then
304 OnGetSharedDataDir(self,Result);
305 end;
306
307 {$IFDEF Unix}
308 function setenv(name:Pchar; value:Pchar; replace:integer):integer;cdecl;external clib name 'setenv';
309 function unsetenv(name:Pchar):integer;cdecl;external clib name 'unsetenv';
310 function SetEnvironmentVariable(name:PChar; value:PChar):boolean;
311 // Set environment variable; if empty string given, remove it.
312 begin
313 result:=false; //assume failure
314 if value = '' then
315 begin
316 // Assume user wants to remove variable.
317 if unsetenv(name)=0 then result:=true;
318 end
319 else
320 begin
321 // Non empty so set the variable
322 if setenv(name, value, 1)=0 then result:=true;
323 end;
324 end;
325 {$ENDIF}
326
327 procedure TCustomIBLocalDBSupport.OnBeforeDatabaseConnect(Sender: TObject;
328 DBParams: TStrings; var DBName: string);
329 begin
330 if not Enabled or (csDesigning in ComponentState) then Exit;
331
332 if not FirebirdAPI.IsEmbeddedServer then
333 raise EIBLocalFatalError.Create(sNoEmbeddedServer);
334
335 InitDatabaseParameters(DBParams,DBName);
336 FActiveDatabasePathName := DBName;
337 SetupFirebirdEnv;
338 end;
339
340 procedure TCustomIBLocalDBSupport.OnDatabaseConnect(Sender: TObject);
341 begin
342 if not Enabled or (csDesigning in ComponentState) or
343 FInUpgrade then Exit; {Avoids problem if RECONNECT used in script}
344
345 UpgradeCheck;
346
347 if not DowngradePending and FNewDBCreated and assigned(FOnNewDatabaseOpen) then
348 OnNewDatabaseOpen(self);
349 FNewDBCreated := false;
350
351 end;
352
353 procedure TCustomIBLocalDBSupport.OnAfterDatabaseDisconnect(Sender: TObject);
354 begin
355 FActiveDatabasePathName := '';
356 end;
357
358 procedure TCustomIBLocalDBSupport.SetFirebirdDirectory(AValue: string);
359 begin
360 if FFirebirdDirectory = AValue then Exit;
361 FFirebirdDirectory := ExcludeTrailingPathDelimiter(AValue);
362 end;
363
364 procedure TCustomIBLocalDBSupport.SetupFirebirdEnv;
365 begin
366 if sysutils.GetEnvironmentVariable('FIREBIRD') = '' then
367 begin
368 if FirebirdDirectory <> '' then
369 begin
370 if not TUpgradeConfFile.IsAbsolutePath(FirebirdDirectory) then
371 FirebirdDirectory := FSharedDataDir + FirebirdDirectory;
372 if FileExists(FirebirdDirectory + DirectorySeparator + 'firebird.conf') then
373 begin
374 SetEnvironmentVariable('FIREBIRD',PChar(FirebirdDirectory));
375 Exit;
376 end;
377 end;
378 if FileExists(FSharedDataDir + 'firebird.conf') then
379 SetEnvironmentVariable('FIREBIRD',PChar(FSharedDataDir));
380 end;
381 end;
382
383 procedure TCustomIBLocalDBSupport.UpgradeCheck;
384 begin
385 if not UpdateVersionNo then
386 Exit;
387
388 if (CurrentDBVersionNo > RequiredVersionNo) and (iblAllowDowngrade in FOptions)then
389 {Possible recovery after failed upgrade}
390 PerformDowngrade(RequiredVersionNo)
391 else
392 if (CurrentDBVersionNo < RequiredVersionNo) and (iblAutoUpgrade in FOptions) then
393 PerformUpgrade(RequiredVersionNo);
394 end;
395
396 function TCustomIBLocalDBSupport.AllowInitialisation: boolean;
397 begin
398 Result := true;
399 end;
400
401 function TCustomIBLocalDBSupport.AllowRestore: boolean;
402 begin
403 Result := true;
404 end;
405
406 procedure TCustomIBLocalDBSupport.CreateDir(DirName: string);
407 var ParentDirName: string;
408 begin
409 ParentDirName := ExtractFileDir(DirName);
410 if not DirectoryExists(ParentDirName) and (ParentDirName <> DirName) then
411 CreateDir(ParentDirName);
412 if not DirectoryExists(DirName) then
413 mkdir(DirName);
414 end;
415
416 procedure TCustomIBLocalDBSupport.Downgrade(DBArchive: string);
417 begin
418 FDownGradeArchive := DBArchive;
419 end;
420
421 procedure TCustomIBLocalDBSupport.DowngradeDone;
422 begin
423 FDownGradeArchive := '';
424 UpdateVersionNo;
425 end;
426
427 function TCustomIBLocalDBSupport.GetDBNameAndPath: string;
428 begin
429 Result := DatabaseName;
430 if VendorName <> '' then
431 Result := VendorName + DirectorySeparator + Result
432 else
433 if Sysutils.VendorName <> '' then
434 Result := SysUtils.VendorName + DirectorySeparator + Result;
435 {$IFDEF UNIX}
436 Result := GetUserDir + '.' + Result;
437 {$ENDIF}
438 {$IFDEF WINDOWS}
439 Result := GetWindowsSpecialDir(CSIDL_LOCAL_APPDATA) + Result;
440 {$ENDIF}
441 if assigned(OnGetDatabaseName) then
442 OnGetDatabaseName(self,Result);
443 end;
444
445 procedure TCustomIBLocalDBSupport.PrepareDBParams(DBParams: TStrings);
446
447 procedure Remove(s: string);
448 var i: integer;
449 begin
450 i := DBParams.IndexOfName(s);
451 if i <> -1 then
452 DBParams.Delete(i);
453 end;
454
455 begin
456 Remove('user_name');
457 Remove('password');
458 {$IFDEF WINDOWS}
459 DBParams.Values['user_name'] := 'SYSDBA';
460 DBParams.Values['password'] := 'masterkey';
461 {$ENDIF}
462 end;
463
464 procedure TCustomIBLocalDBSupport.SetDatabaseName(AValue: string);
465 begin
466 if FDatabaseName = AValue then Exit;
467 FDatabaseName := ExtractFileName(AValue);
468 end;
469
470 class procedure TCustomIBLocalDBSupport.SetDBParams(aService: TIBCustomService;
471 DBParams: TStrings);
472 var i: integer;
473 j: integer;
474 k: integer;
475 ParamName: string;
476 begin
477 aService.Params.Clear;
478 for i := 0 to DBParams.Count - 1 do
479 begin
480 ParamName := DBParams[i];
481 k := Pos('=',ParamName);
482 if k > 0 then system.Delete(ParamName,k,Length(ParamName)-k+1);
483 for j := 1 to isc_spb_last_spb_constant do
484 if ParamName = SPBConstantNames[j] then
485 begin
486 aService.Params.Add(DBParams[i]);
487 break;
488 end;
489 end;
490 end;
491
492 function TCustomIBLocalDBSupport.UpdateVersionNo: boolean;
493 begin
494 Result := assigned(OnGetDBVersionNo);
495 if Result then
496 OnGetDBVersionNo(self,FCurrentDBVersionNo); {Update Version No}
497 end;
498
499 constructor TCustomIBLocalDBSupport.Create(aOwner: TComponent);
500 begin
501 inherited Create(aOwner);
502 FEnabled := true;
503 FIBBase := TIBBase.Create(self);
504 FIBBase.AfterDatabaseConnect := @OnDatabaseConnect;
505 FIBBase.BeforeDatabaseConnect := @OnBeforeDatabaseConnect;
506 FIBBase.AfterDatabaseDisconnect := @OnAfterDatabaseDisconnect;
507 FUpgradeConfFile := 'upgrade.conf';
508 FOptions := [iblAutoUpgrade, iblAllowDowngrade];
509 FSharedDataDir := MapSharedDataDir(ExtractFilePath(ParamStr(0)));
510 end;
511
512 destructor TCustomIBLocalDBSupport.Destroy;
513 begin
514 if assigned(FIBBase) then FreeAndNil(FIBBase);
515 inherited Destroy;
516 end;
517
518 function TCustomIBLocalDBSupport.DowngradePending: boolean;
519 begin
520 Result := FDownGradeArchive <> '';
521 end;
522
523 procedure TCustomIBLocalDBSupport.NewDatabase;
524 var TempDBParams: TStringList;
525 begin
526 CheckEnabled;
527 if not AllowInitialisation then Exit;
528
529 TempDBParams := TStringList.Create;
530 try
531 TempDBParams.Assign(Database.Params);
532 Database.Connected := false;
533 PrepareDBParams(TempDBParams);
534 CreateDatabase(Database.DatabaseName,TempDBParams,true);
535 finally
536 TempDBParams.Free;
537 end;
538 Database.Connected := true;
539 end;
540
541 procedure TCustomIBLocalDBSupport.PerformDowngrade(TargetVersionNo: integer);
542 var DBArchive: string;
543 begin
544 DBArchive := ChangeFileExt(ActiveDatabasePathName,'') +
545 '.' + IntToStr(TargetVersionNo) + '.gbk';
546 if FileExists(DBArchive) then
547 Downgrade(DBArchive)
548 else
549 raise EIBLocalFatalError.CreateFmt(sNoDowngrade,[CurrentDBVersionNo,TargetVersionNo]);
550 end;
551
552 procedure TCustomIBLocalDBSupport.PerformUpgrade(TargetVersionNo: integer);
553
554 function GetUpgradeConfFile: string;
555 begin
556 Result := UpgradeConfFile;
557 if Result = '' then Exit;
558
559 if not TUpgradeConfFile.IsAbsolutePath(Result) then
560 Result := FSharedDataDir + Result;
561 end;
562
563 begin
564 if FInUpgrade then Exit;
565
566 FUpgradeConf := TUpgradeConfFile.Create(GetUpgradeConfFile);
567 try
568 FUpgradeConf.CheckUpgradeAvailable(TargetVersionNo);
569 FInUpgrade := true;
570 try
571 RunUpgradeDatabase(TargetVersionNo);
572 finally
573 FInUpgrade := false;
574 end;
575 finally
576 FreeAndNil(FUpgradeConf);
577 end;
578 end;
579
580 procedure TCustomIBLocalDBSupport.InitDatabaseParameters(DBParams: TStrings;
581 var DBName: string);
582 begin
583 PrepareDBParams(DBParams);
584 DBName := GetDBNameAndPath;
585 if not FileExists(DBName) then
586 CreateDatabase(DBName,DBParams,false);
587 end;
588
589 procedure TCustomIBLocalDBSupport.Loaded;
590 begin
591 inherited Loaded;
592 if (Database <> nil) and (Database.DatabaseName = '') then
593 Database.DatabaseName := ' '; {Avoid CheckDatabaseName Error}
594 DoDirSeparators(FEmptyDBArchive);
595 DoDirSeparators(FFirebirdDirectory);
596 DoDirSeparators(FUpgradeConfFile);
597 end;
598
599 procedure TCustomIBLocalDBSupport.RestoreDatabase(filename: string);
600 var TempDBParams: TStringList;
601 begin
602 CheckEnabled;
603 if not AllowRestore then Exit;
604
605 TempDBParams := TStringList.Create;
606 try
607 TempDBParams.Assign(Database.Params);
608 PrepareDBParams(TempDBParams);
609 Database.Connected := false;
610 RestoreDatabaseFromArchive(Database.DatabaseName,TempDBParams,filename);
611 finally
612 TempDBParams.Free;
613 end;
614 Database.Connected := true;
615 end;
616
617 procedure TCustomIBLocalDBSupport.SaveDatabase(filename: string);
618 var TempDBParams: TStringList;
619 begin
620 CheckEnabled;
621 TempDBParams := TStringList.Create;
622 try
623 TempDBParams.Assign(Database.Params);
624 PrepareDBParams(TempDBParams);
625 SaveDatabaseToArchive(Database.DatabaseName,TempDBParams,filename);
626 finally
627 TempDBParams.Free;
628 end;
629 end;
630
631 end.