ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/iblocaldb/nongui/IBXCustomIBLocalDBSupport.pas
Revision: 315
Committed: Thu Feb 25 11:56:36 2021 UTC (3 years, 8 months ago) by tony
Content type: text/x-pascal
File size: 21724 byte(s)
Log Message:
Updated for IBX 4 release

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, IBXUpgradeConfFile, ibxscript,
34 IB, IBXServices;
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 EIBLocalException = class(Exception);
84
85
86 { TCustomIBLocalDBSupport }
87
88 TCustomIBLocalDBSupport = class(TComponent)
89 private
90 FMinimumVersionNo: integer;
91 { Private declarations }
92 FServicesConnection: TIBXServicesConnection;
93 FBackupService: TIBXServerSideBackupService;
94 FRestoreService: TIBXServerSideRestoreService;
95 FActiveDatabasePathName: string;
96 FCurrentDBVersionNo: integer;
97 FEmptyDBArchive: string;
98 FEnabled: boolean;
99 FFirebirdDirectory: string;
100 FIBBase: TIBBase;
101 FDatabaseName: string;
102 FOnGetDatabaseName: TOnGetDatabaseName;
103 FOnGetDBVersionNo: TOnGetDBVersionNo;
104 FOnGetSharedDataDir: TOnGetSharedDataDir;
105 FOnNewDatabaseOpen: TNotifyEvent;
106 FOptions: TIBLocalOptions;
107 FRequiredVersionNo: integer;
108 FUpgradeConfFile: string;
109 FNewDBCreated: boolean;
110 FVendorName: string;
111 FInUpgrade: boolean;
112 FDownGradeArchive: string;
113 FSharedDataDir: string;
114 FUpgradeConf: TUpgradeConfFile;
115 FInOnCreateDB: boolean;
116 FUpgradeFailed: boolean;
117 procedure CheckEnabled;
118 function GetDatabase: TIBDatabase;
119 function GetSharedDataDir: string;
120 procedure SetDatabase(AValue: TIBDatabase);
121 function GetDBNameAndPath: string;
122 function MapSharedDataDir(aDataDir: string): string;
123 procedure OnBeforeDatabaseConnect(Sender: TObject; DBParams: TStrings;
124 var DBName: string; var CreateIfNotExists: boolean);
125 procedure OnDatabaseConnected(Sender: TObject);
126 procedure OnAfterDatabaseDisconnect(Sender: TObject);
127 procedure OnCreateDatabase(Sender: TObject);
128 procedure PrepareDBParams(DBParams: TStrings);
129 procedure SetDatabaseName(AValue: string);
130 procedure SetFirebirdDirectory(AValue: string);
131 procedure SetupFirebirdEnv;
132 procedure UpgradeCheck;
133 protected
134 { Protected declarations }
135 procedure Add2Log(Sender: TObject; Msg: string); virtual;
136 function AllowInitialisation: boolean; virtual;
137 function AllowRestore: boolean; virtual;
138 procedure CreateDir(DirName: string);
139 function InternalCreateNewDatabase(DBArchive: string): boolean; virtual; abstract;
140 procedure Downgrade(DBArchive: string); virtual;
141 procedure DowngradeDone;
142 procedure Loaded; override;
143 function RestoreDatabaseFromArchive(aFilename: string): boolean; virtual; abstract;
144 function RunUpgradeDatabase(TargetVersionNo: integer): boolean; virtual; abstract;
145 function SaveDatabaseToArchive(aFilename: string): boolean; virtual; abstract;
146 function UpdateVersionNo: boolean;
147 property DownGradeArchive: string read FDownGradeArchive;
148 property UpgradeConf: TUpgradeConfFile read FUpgradeConf;
149 property RestoreService: TIBXServerSideRestoreService read FRestoreService;
150 property BackupService: TIBXServerSideBackupService read FBackupService;
151 public
152 { Public declarations }
153 constructor Create(aOwner: TComponent); override;
154 destructor Destroy; override;
155
156 function DowngradePending: boolean;
157
158 {NewDatabase: called to reinitialise the local database using the initialisation
159 archive. Overwrites existing data so use carefully.}
160 procedure NewDatabase;
161
162 {Perform a downgrade to target version if backup archive available.
163 Note: normally called from UpgradeCheck if iblAllowDowngrade in Options}
164 procedure PerformDowngrade(TargetVersionNo: integer);
165
166 {Perform schema upgrade to target version if upgrade scripts available.
167 Note: normally called from UpgradeCheck if iblAllowUpgrade in Options}
168 procedure PerformUpgrade(TargetVersionNo: integer);
169
170 {RestoreDatabase: overwrites the existing local database with the specified
171 gbak format archive. User is prompted to locate archive if filename empty.}
172 procedure RestoreDatabase (filename: string = '');
173
174 {SaveDatabase: Saves the current database into a gbak format archive. User
175 is prompted for archive filename if filename empty.}
176 procedure SaveDatabase(filename: string = '');
177
178 property ActiveDatabasePathName: string read FActiveDatabasePathName;
179 property CurrentDBVersionNo: integer read FCurrentDBVersionNo;
180 property InOnCreateDB: boolean read FInOnCreateDB;
181 property SharedDataDir: string read GetSharedDataDir;
182 property ServicesConnection: TIBXServicesConnection read FServicesConnection;
183
184 { Likely to be Published declarations }
185 property Database: TIBDatabase read GetDatabase write SetDatabase;
186 property DatabaseName: string read FDatabaseName write SetDatabaseName;
187 property Enabled: boolean read FEnabled write FEnabled default true;
188 property EmptyDBArchive: string read FEmptyDBArchive write FEmptyDBArchive;
189 property FirebirdDirectory: string read FFirebirdDirectory write SetFirebirdDirectory;
190 property Options: TIBLocalOptions read FOptions write FOptions;
191 property RequiredVersionNo: integer read FRequiredVersionNo write FRequiredVersionNo;
192 property MinimumVersionNo: integer read FMinimumVersionNo write FMinimumVersionNo;
193 property UpgradeConfFile: string read FUpgradeConfFile write FUpgradeConfFile;
194 property VendorName: string read FVendorName write FVendorName;
195 property OnGetDatabaseName: TOnGetDatabaseName read FOnGetDatabaseName write FOnGetDatabaseName;
196 property OnGetDBVersionNo: TOnGetDBVersionNo read FOnGetDBVersionNo write FOnGetDBVersionNo;
197 property OnNewDatabaseOpen: TNotifyEvent read FOnNewDatabaseOpen write FOnNewDatabaseOpen;
198 property OnGetSharedDataDir: TOnGetSharedDataDir read FOnGetSharedDataDir write FOnGetSharedDataDir;
199 end;
200
201 EIBLocalFatalError = class(Exception);
202
203 implementation
204
205 {$IFDEF Unix} uses initc, regexpr {$ENDIF}
206 {$IFDEF WINDOWS} uses Windows ,Windirs {$ENDIF}, IBUtils, IBMessages;
207
208 resourcestring
209 sNoDowngrade = 'Database Schema is %d. Unable to downgrade to version %d';
210 sLocalDBDisabled = 'Local Database Access Disabled';
211 sEmptyDBArchiveMissing = 'Unable to create database - no empty DB archive specified';
212 sEmptyDBArchiveNotFound = 'Unable to create database - empty DB archive file (%s) not found';
213 sNoEmbeddedServer = 'Firebird Embedded Server is required but is not installed';
214 sCreateFailed = 'Unable to Create Personal Database';
215 sDowngrade = 'Downgrading to version %d';
216 sSkipUpgrade = 'Previous attempt at upgrade to %d failed. Skipping upgrade';
217
218 { TCustomIBLocalDBSupport }
219
220
221 procedure TCustomIBLocalDBSupport.CheckEnabled;
222 begin
223 if not Enabled then
224 raise EIBLocalException.Create(sLocalDBDisabled);
225 end;
226
227 function TCustomIBLocalDBSupport.GetDatabase: TIBDatabase;
228 begin
229 Result := FIBBase.Database;
230 end;
231
232 function TCustomIBLocalDBSupport.GetSharedDataDir: string;
233 begin
234 if FSharedDataDir = '' then
235 FSharedDataDir := MapSharedDataDir(ExtractFilePath(ParamStr(0)));
236 Result := FSharedDataDir;
237 end;
238
239 procedure TCustomIBLocalDBSupport.SetDatabase(AValue: TIBDatabase);
240 begin
241 FIBBase.Database := AValue;
242 end;
243
244 function TCustomIBLocalDBSupport.MapSharedDataDir(aDataDir: string): string;
245 {$IFDEF UNIX}
246 var RegexObj: TRegExpr;
247 {$ENDIF}
248 begin
249 Result := aDataDir;
250 {$IFDEF UNIX}
251
252 {Under Unix transform application exe paths that are in installed locations
253 e.g. /usr/local/bin to corresponding shared data locations e.g. /usr/local/shared}
254 RegexObj := TRegExpr.Create;
255 try
256 RegexObj.Expression := '^/usr(/local|)/(s|)bin/.*$';
257 if RegexObj.Exec(aDataDir) then
258 Result := '/usr' + RegexObj.Match[1] + '/share/' + ApplicationName + '/';
259 finally
260 RegexObj.Free;
261 end;
262 {$ENDIF}
263 if assigned (FOnGetSharedDataDir) then
264 OnGetSharedDataDir(self,Result);
265 {Ensure a trailing separator}
266 if (Length(Result) > 0) and (Result[Length(Result)] <> DirectorySeparator) then
267 Result := Result + DirectorySeparator;
268 end;
269
270 {$IFDEF Unix}
271 function setenv(name:Pchar; value:Pchar; replace:integer):integer;cdecl;external clib name 'setenv';
272 function unsetenv(name:Pchar):integer;cdecl;external clib name 'unsetenv';
273 function SetEnvironmentVariable(name:PChar; value:PChar):boolean;
274 // Set environment variable; if empty string given, remove it.
275 begin
276 result:=false; //assume failure
277 if value = '' then
278 begin
279 // Assume user wants to remove variable.
280 if unsetenv(name)=0 then result:=true;
281 end
282 else
283 begin
284 // Non empty so set the variable
285 if setenv(name, value, 1)=0 then result:=true;
286 end;
287 end;
288 {$ENDIF}
289
290 procedure TCustomIBLocalDBSupport.OnBeforeDatabaseConnect(Sender: TObject;
291 DBParams: TStrings; var DBName: string; var CreateIfNotExists: boolean);
292 begin
293 if FInOnCreateDB or not Enabled or (csDesigning in ComponentState) then Exit;
294
295 if not assigned(Database) or not Database.FirebirdAPI.IsEmbeddedServer then
296 raise EIBLocalFatalError.Create(sNoEmbeddedServer);
297
298 DBName := GetDBNameAndPath;
299 CreateDir(ExtractFileDir(DBName));
300 FActiveDatabasePathName := DBName;
301 SetupFirebirdEnv;
302 CreateIfNotExists := true;
303 PrepareDBParams(DBParams);
304 ServicesConnection.SetDBParams(DBParams);
305 end;
306
307 procedure TCustomIBLocalDBSupport.OnDatabaseConnected(Sender: TObject);
308 begin
309 if FInOnCreateDB then Exit;
310 if not Enabled or (csDesigning in ComponentState) or
311 FInUpgrade then Exit; {Avoids problem if RECONNECT used in script}
312
313 UpgradeCheck;
314
315 if not DowngradePending and FNewDBCreated and assigned(FOnNewDatabaseOpen) then
316 OnNewDatabaseOpen(self);
317 FNewDBCreated := false;
318 end;
319
320 procedure TCustomIBLocalDBSupport.OnAfterDatabaseDisconnect(Sender: TObject);
321 begin
322 FActiveDatabasePathName := '';
323 end;
324
325 procedure TCustomIBLocalDBSupport.OnCreateDatabase(Sender: TObject);
326 var DBArchive: string;
327 begin
328 if FInOnCreateDB then Exit;
329
330 FInOnCreateDB := true;
331 try
332 CheckEnabled;
333 DBArchive := EmptyDBArchive;
334 if DBArchive = '' then
335 raise EIBLocalException.Create(sEmptyDBArchiveMissing);
336
337 if not TUpgradeConfFile.IsAbsolutePath(DBArchive) then
338 DBArchive := SharedDataDir + DBArchive;
339
340 if not FileExists(DBArchive) then
341 raise EIBLocalException.CreateFmt(sEmptyDBArchiveNotFound,[DBArchive]);
342
343 ServicesConnection.ConnectUsing(Database);
344 try
345 if not InternalCreateNewDatabase(DBArchive) then
346 begin
347 Database.DropDatabase;
348 raise EIBLocalException.Create(sCreateFailed);
349 end;
350 finally
351 ServicesConnection.Connected := false;
352 end;
353 FNewDBCreated := true;
354 finally
355 FInOnCreateDB := false;
356 end;
357 end;
358
359 procedure TCustomIBLocalDBSupport.SetFirebirdDirectory(AValue: string);
360 begin
361 if FFirebirdDirectory = AValue then Exit;
362 FFirebirdDirectory := ExcludeTrailingPathDelimiter(AValue);
363 end;
364
365 procedure TCustomIBLocalDBSupport.SetupFirebirdEnv;
366 var sdd: string;
367 begin
368 if sysutils.GetEnvironmentVariable('FIREBIRD') = '' then
369 begin
370 if FirebirdDirectory <> '' then
371 begin
372 if not TUpgradeConfFile.IsAbsolutePath(FirebirdDirectory) then
373 FirebirdDirectory := SharedDataDir + FirebirdDirectory;
374 if FileExists(FirebirdDirectory + DirectorySeparator + 'firebird.conf') then
375 begin
376 SetEnvironmentVariable('FIREBIRD',PChar(FirebirdDirectory));
377 Exit;
378 end;
379 end;
380 if FileExists(SharedDataDir + 'firebird.conf') then
381 begin
382 sdd := SharedDataDir;
383 SetEnvironmentVariable('FIREBIRD',PChar(sdd));
384 end;
385 end;
386 end;
387
388 procedure TCustomIBLocalDBSupport.UpgradeCheck;
389 begin
390 if not UpdateVersionNo then
391 Exit;
392
393 if (CurrentDBVersionNo > RequiredVersionNo) and (iblAllowDowngrade in FOptions)then
394 {Possible recovery after failed upgrade}
395 PerformDowngrade(RequiredVersionNo)
396 else
397 if (CurrentDBVersionNo < RequiredVersionNo) and (iblAutoUpgrade in FOptions) then
398 begin
399 if FUpgradeFailed then
400 begin
401 Add2Log(self,Format(sSkipUpgrade,[RequiredVersionNo]));
402 if MinimumVersionNo > CurrentDBVersionNo then
403 begin
404 Database.ForceClose;
405 IBError(ibxDBVersionProblem,[CurrentDBVersionNo, MinimumVersionNo]);
406 end
407 end
408 else
409 PerformUpgrade(RequiredVersionNo);
410 end;
411 end;
412
413 procedure TCustomIBLocalDBSupport.Add2Log(Sender: TObject; Msg: string);
414 begin
415 //Do nothing
416 end;
417
418 function TCustomIBLocalDBSupport.AllowInitialisation: boolean;
419 begin
420 Result := true;
421 end;
422
423 function TCustomIBLocalDBSupport.AllowRestore: boolean;
424 begin
425 Result := true;
426 end;
427
428 procedure TCustomIBLocalDBSupport.CreateDir(DirName: string);
429 var ParentDirName: string;
430 begin
431 ParentDirName := ExtractFileDir(DirName);
432 if not DirectoryExists(ParentDirName) and (ParentDirName <> DirName) then
433 CreateDir(ParentDirName);
434 if not DirectoryExists(DirName) then
435 mkdir(DirName);
436 end;
437
438 procedure TCustomIBLocalDBSupport.Downgrade(DBArchive: string);
439 begin
440 FDownGradeArchive := DBArchive;
441 end;
442
443 procedure TCustomIBLocalDBSupport.DowngradeDone;
444 begin
445 FDownGradeArchive := '';
446 UpdateVersionNo;
447 end;
448
449 function TCustomIBLocalDBSupport.GetDBNameAndPath: string;
450 begin
451 Result := DatabaseName;
452 if VendorName <> '' then
453 Result := VendorName + DirectorySeparator + Result
454 else
455 if Sysutils.VendorName <> '' then
456 Result := SysUtils.VendorName + DirectorySeparator + Result;
457 {$IFDEF UNIX}
458 Result := GetUserDir + '.' + Result;
459 {$ENDIF}
460 {$IFDEF WINDOWS}
461 Result := GetWindowsSpecialDir(CSIDL_LOCAL_APPDATA) + Result;
462 {$ENDIF}
463 if assigned(OnGetDatabaseName) then
464 OnGetDatabaseName(self,Result);
465 end;
466
467 procedure TCustomIBLocalDBSupport.PrepareDBParams(DBParams: TStrings);
468
469 procedure Remove(s: string);
470 var i: integer;
471 begin
472 i := DBParams.IndexOfName(s);
473 if i <> -1 then
474 DBParams.Delete(i);
475 end;
476
477 begin
478 {$IFDEF UNIX}
479 if Database.FirebirdAPI.GetClientMajor >= 3 then
480 begin
481 Remove('user_name');
482 Remove('password');
483 DBParams.Values['user_name'] := 'SYSDBA';
484 end;
485 {$ENDIF}
486 {$IFDEF WINDOWS}
487 DBParams.Values['user_name'] := 'SYSDBA';
488 DBParams.Values['password'] := 'masterkey';
489 {$ENDIF}
490 end;
491
492 procedure TCustomIBLocalDBSupport.SetDatabaseName(AValue: string);
493 begin
494 if FDatabaseName = AValue then Exit;
495 FDatabaseName := ExtractFileName(AValue);
496 end;
497
498 function TCustomIBLocalDBSupport.UpdateVersionNo: boolean;
499 begin
500 Result := assigned(OnGetDBVersionNo);
501 if Result then
502 OnGetDBVersionNo(self,FCurrentDBVersionNo); {Update Version No}
503 end;
504
505 constructor TCustomIBLocalDBSupport.Create(aOwner: TComponent);
506 begin
507 inherited Create(aOwner);
508 FEnabled := true;
509 FIBBase := TIBBase.Create(self);
510 FIBBase.AfterDatabaseConnect := @OnDatabaseConnected;
511 FIBBase.BeforeDatabaseConnect := @OnBeforeDatabaseConnect;
512 FIBBase.AfterDatabaseDisconnect := @OnAfterDatabaseDisconnect;
513 FIBBase.OnCreateDatabase := @OnCreateDatabase;
514 FUpgradeConfFile := 'upgrade.conf';
515 FOptions := [iblAutoUpgrade, iblAllowDowngrade];
516 FServicesConnection := TIBXServicesConnection.Create(self);
517 FServicesConnection.LoginPrompt := false;
518 FServicesConnection.Params.Values['user_name'] := 'SYSDBA';
519 FBackupService := TIBXServerSideBackupService.Create(self);
520 FBackupService.ServicesConnection := ServicesConnection;
521 FBackupService.Verbose := true;
522 FRestoreService := TIBXServerSideRestoreService.Create(self);
523 FRestoreService.ServicesConnection := ServicesConnection;
524 FRestoreService.Verbose := true;
525 end;
526
527 destructor TCustomIBLocalDBSupport.Destroy;
528 begin
529 if assigned(FIBBase) then FreeAndNil(FIBBase);
530 inherited Destroy;
531 end;
532
533 function TCustomIBLocalDBSupport.DowngradePending: boolean;
534 begin
535 Result := FDownGradeArchive <> '';
536 end;
537
538 procedure TCustomIBLocalDBSupport.NewDatabase;
539 begin
540 CheckEnabled;
541 if not AllowInitialisation then Exit;
542
543 Database.DropDatabase;
544 Database.Connected := true;
545 end;
546
547 procedure TCustomIBLocalDBSupport.PerformDowngrade(TargetVersionNo: integer);
548 var DBArchive: string;
549 begin
550 DBArchive := ChangeFileExt(ActiveDatabasePathName,'') +
551 '.' + IntToStr(TargetVersionNo) + '.gbk';
552 if FileExists(DBArchive) then
553 begin
554 Add2Log(self,Format(sDowngrade,[TargetVersionNo]));
555 Downgrade(DBArchive)
556 end
557 else
558 raise EIBLocalFatalError.CreateFmt(sNoDowngrade,[CurrentDBVersionNo,TargetVersionNo]);
559 end;
560
561 procedure TCustomIBLocalDBSupport.PerformUpgrade(TargetVersionNo: integer);
562
563 function GetUpgradeConfFile: string;
564 begin
565 Result := UpgradeConfFile;
566 if Result = '' then Exit;
567
568 if not TUpgradeConfFile.IsAbsolutePath(Result) then
569 Result := SharedDataDir + Result;
570 end;
571
572 var OldVersionNo: integer;
573
574 begin
575 if FInUpgrade then Exit;
576
577 OldVersionNo := CurrentDBVersionNo;
578 FUpgradeConf := TUpgradeConfFile.Create(GetUpgradeConfFile);
579 try
580 FUpgradeConf.CheckUpgradeAvailable(TargetVersionNo);
581 FInUpgrade := true;
582 try
583 ServicesConnection.ConnectUsing(Database);
584 try
585 if not RunUpgradeDatabase(TargetVersionNo) then
586 begin
587 {DownGrade if possible}
588 PerformDowngrade(OldVersionNo);
589 Database.ForceClose;
590 FUpgradeFailed := true;
591 IBError(ibxeUpgradeFailed,[CurrentDBVersionNo]);
592 end;
593 finally
594 ServicesConnection.Connected := false;
595 end;
596 finally
597 FInUpgrade := false;
598 end;
599 finally
600 FreeAndNil(FUpgradeConf);
601 end;
602 FUpgradeFailed := false;
603 if CurrentDBVersionNo < MinimumVersionNo then
604 begin
605 Database.ForceClose;
606 IBError(ibxDBVersionProblem,[CurrentDBVersionNo,MinimumVersionNo]);
607 end;
608 end;
609
610 procedure TCustomIBLocalDBSupport.Loaded;
611 begin
612 inherited Loaded;
613 if (Database <> nil) and (Database.DatabaseName = '') then
614 Database.DatabaseName := ' '; {Avoid CheckDatabaseName Error}
615 DoDirSeparators(FEmptyDBArchive);
616 DoDirSeparators(FFirebirdDirectory);
617 DoDirSeparators(FUpgradeConfFile);
618 end;
619
620 procedure TCustomIBLocalDBSupport.RestoreDatabase(filename: string);
621 begin
622 CheckEnabled;
623 if not AllowRestore then Exit;
624
625 ServicesConnection.ConnectUsing(Database);
626 Database.Connected := false;
627 try
628 RestoreDatabaseFromArchive(filename);
629 finally
630 ServicesConnection.Connected := false;
631 Database.Connected := true;
632 end;
633 end;
634
635 procedure TCustomIBLocalDBSupport.SaveDatabase(filename: string);
636 begin
637 CheckEnabled;
638 ServicesConnection.ConnectUsing(Database);
639 try
640 SaveDatabaseToArchive(filename);
641 finally
642 ServicesConnection.Connected := false;
643 end;
644 end;
645
646 end.