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, 2 months ago) by tony
Content type: text/x-pascal
File size: 21724 byte(s)
Log Message:
Updated for IBX 4 release

File Contents

# User Rev Content
1 tony 209 (*
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 tony 315 FMinimumVersionNo: integer;
91 tony 209 { 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 tony 272 FInOnCreateDB: boolean;
116 tony 315 FUpgradeFailed: boolean;
117 tony 209 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 tony 315 procedure Add2Log(Sender: TObject; Msg: string); virtual;
136 tony 209 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 tony 272 property InOnCreateDB: boolean read FInOnCreateDB;
181 tony 209 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 tony 315 property MinimumVersionNo: integer read FMinimumVersionNo write FMinimumVersionNo;
193 tony 209 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 tony 315 {$IFDEF WINDOWS} uses Windows ,Windirs {$ENDIF}, IBUtils, IBMessages;
207 tony 209
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 tony 315 sDowngrade = 'Downgrading to version %d';
216     sSkipUpgrade = 'Previous attempt at upgrade to %d failed. Skipping upgrade';
217 tony 209
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 tony 272 if FInOnCreateDB or not Enabled or (csDesigning in ComponentState) then Exit;
294 tony 209
295 tony 263 if not assigned(Database) or not Database.FirebirdAPI.IsEmbeddedServer then
296 tony 209 raise EIBLocalFatalError.Create(sNoEmbeddedServer);
297    
298     DBName := GetDBNameAndPath;
299     CreateDir(ExtractFileDir(DBName));
300     FActiveDatabasePathName := DBName;
301     SetupFirebirdEnv;
302     CreateIfNotExists := true;
303     PrepareDBParams(DBParams);
304 tony 315 ServicesConnection.SetDBParams(DBParams);
305 tony 209 end;
306    
307     procedure TCustomIBLocalDBSupport.OnDatabaseConnected(Sender: TObject);
308     begin
309 tony 272 if FInOnCreateDB then Exit;
310 tony 209 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 tony 272 if FInOnCreateDB then Exit;
329 tony 209
330 tony 272 FInOnCreateDB := true;
331     try
332     CheckEnabled;
333     DBArchive := EmptyDBArchive;
334     if DBArchive = '' then
335     raise EIBLocalException.Create(sEmptyDBArchiveMissing);
336 tony 209
337 tony 272 if not TUpgradeConfFile.IsAbsolutePath(DBArchive) then
338     DBArchive := SharedDataDir + DBArchive;
339 tony 209
340 tony 272 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 tony 209 end;
353 tony 272 FNewDBCreated := true;
354 tony 209 finally
355 tony 272 FInOnCreateDB := false;
356 tony 209 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 tony 315 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 tony 209 end;
412    
413 tony 315 procedure TCustomIBLocalDBSupport.Add2Log(Sender: TObject; Msg: string);
414     begin
415     //Do nothing
416     end;
417    
418 tony 209 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 tony 315 {$IFDEF UNIX}
479     if Database.FirebirdAPI.GetClientMajor >= 3 then
480     begin
481 tony 209 Remove('user_name');
482     Remove('password');
483     DBParams.Values['user_name'] := 'SYSDBA';
484 tony 315 end;
485     {$ENDIF}
486     {$IFDEF WINDOWS}
487     DBParams.Values['user_name'] := 'SYSDBA';
488     DBParams.Values['password'] := 'masterkey';
489     {$ENDIF}
490 tony 209 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 tony 315 FBackupService.ServicesConnection := ServicesConnection;
521 tony 209 FBackupService.Verbose := true;
522     FRestoreService := TIBXServerSideRestoreService.Create(self);
523 tony 315 FRestoreService.ServicesConnection := ServicesConnection;
524 tony 209 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 tony 315 begin
554     Add2Log(self,Format(sDowngrade,[TargetVersionNo]));
555 tony 209 Downgrade(DBArchive)
556 tony 315 end
557 tony 209 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 tony 315 var OldVersionNo: integer;
573    
574 tony 209 begin
575     if FInUpgrade then Exit;
576    
577 tony 315 OldVersionNo := CurrentDBVersionNo;
578 tony 209 FUpgradeConf := TUpgradeConfFile.Create(GetUpgradeConfFile);
579     try
580     FUpgradeConf.CheckUpgradeAvailable(TargetVersionNo);
581     FInUpgrade := true;
582     try
583     ServicesConnection.ConnectUsing(Database);
584     try
585 tony 315 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 tony 209 finally
594     ServicesConnection.Connected := false;
595     end;
596     finally
597     FInUpgrade := false;
598     end;
599     finally
600     FreeAndNil(FUpgradeConf);
601     end;
602 tony 315 FUpgradeFailed := false;
603     if CurrentDBVersionNo < MinimumVersionNo then
604     begin
605     Database.ForceClose;
606     IBError(ibxDBVersionProblem,[CurrentDBVersionNo,MinimumVersionNo]);
607     end;
608 tony 209 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.