1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
| unit uDataModule;
interface
uses
System.SysUtils, System.Classes,
FireDAC.Comp.Client, FireDAC.Stan.Def, FireDAC.Stan.Async,
FireDAC.DApt, FireDAC.Phys.SQLite, FireDAC.Phys.SQLiteWrapper,
FireDAC.Phys, FireDAC.UI.Intf, FireDAC.Comp.UI, FireDAC.Stan.Intf,
FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.Phys.Intf, FireDAC.Stan.Pool,
FireDAC.VCLUI.Wait, Data.DB, FireDAC.Phys.SQLiteDef, FireDAC.Stan.ExprFuncs,
FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf, Data.Bind.Components,
Data.Bind.DBScope, FireDAC.Comp.DataSet;
type
TdmDB = class(TDataModule)
FDConnectionMem: TFDConnection;
FDPhysSQLiteDriverLinkPolaris: TFDPhysSQLiteDriverLink;
FDGUIxWaitCursor1: TFDGUIxWaitCursor;
dsVilles: TDataSource;
fdqVilles: TFDQuery;
bsVilles: TBindSourceDB;
FDSQLiteValidate1: TFDSQLiteValidate;
procedure DataModuleCreate(Sender: TObject);
procedure DataModuleDestroy(Sender: TObject);
private
FModified: Boolean;
FDBFile: string;
procedure LoadDBInMemory;
procedure SaveDBToDisk(ASaveWithTimestamp: Boolean = True);
procedure SetDBFile(const AValue: string);
public
property DBFile: string read FDBFile write SetDBFile;
end;
var
dmDB: TdmDB;
implementation
{%CLASSGROUP 'Vcl.Controls.TControl'}
{$R *.dfm}
uses
Vcl.Dialogs;
procedure TdmDB.DataModuleCreate(Sender: TObject);
begin
FModified := False;
end;
procedure TdmDB.DataModuleDestroy(Sender: TObject);
begin
// Sauver la DB mémoire en sortie
// ShowMessage(Format('Il y a %d enregistrements modifiés', [fdqVilles.ChangeCount]));
// ShowMessage(Format('Il y a %s enregistrements en attente', [BoolToStr(fdqVilles.UpdatesPending, true)]));
if FModified then
SaveDBToDisk;
end;
procedure TdmDB.LoadDBInMemory;
var
DiskConn: TFDConnection;
Backup: TFDSQLiteBackup;
begin
// --- Connexion mémoire partagée ---
FDConnectionMem.DriverName := 'SQLite';
FDConnectionMem.Params.Values['Database'] := 'file::memory:?cache=shared';
FDConnectionMem.LoginPrompt := False;
FDConnectionMem.Connected := True;
// --- Connexion disque ---
DiskConn := TFDConnection.Create(nil);
try
DiskConn.DriverName := 'SQLite';
DiskConn.Params.Database := FDBFile;
DiskConn.Params.Add('OpenMode=ReadWrite'); // lecture/écriture possible
DiskConn.LoginPrompt := False;
DiskConn.Connected := True;
// --- Backup disque -> mémoire ---
Backup := TFDSQLiteBackup.Create(nil);
try
Backup.Database := DiskConn.Params.Database; // base disque
Backup.DestDatabaseObj := FDConnectionMem.CliObj; // base mémoire
Backup.DriverLink := FDPhysSQLiteDriverLinkPolaris; // Nécessaire pour fonctionner.
Backup.DestMode := smCreate;
Backup.Backup;
finally
Backup.Free;
end;
finally
DiskConn.Free;
end;
end;
procedure TdmDB.SaveDBToDisk(ASaveWithTimestamp: Boolean);
var
Backup: TFDSQLiteBackup;
LPath, LName, LExt: string;
LDBFileOut: string;
begin
if not FDConnectionMem.Connected then
Exit;
// Création de la copie de la base sur disque;
if ASaveWithTimestamp then
begin
LPath := ExtractFilePath(FDBFile);
LName := ChangeFileExt(ExtractFileName(FDBFile), '');
LExt := ExtractFileExt(FDBFile);
LDBFileOut := Format('%s%s-%s%s', [LPath, LName, FormatDateTime('yyyymmdd_hhnnss', Now), LExt]);
end
else
LDBFileOut := FDBFile;
// Equivalent a la commande VACUUM pour réduire la taille de la base...
FDSQLiteValidate1.Sweep;
Backup := TFDSQLiteBackup.Create(nil);
try
Backup.DatabaseObj := FDConnectionMem.CliObj; // mémoire partagée
Backup.DestDatabase := LDBFileOut; // fichier disque
Backup.DriverLink := FDPhysSQLiteDriverLinkPolaris; // Nécessaire pour fonctionner.
Backup.DestMode := smCreate; // recrée le fichier
Backup.Backup;
finally
Backup.Free;
end;
end;
procedure TdmDB.SetDBFile(const AValue: string);
begin
if (AValue <> EmptyStr) and FileExists(AValue) then
begin
FDBFile := AValue;
// Charger en mémoire partagée
LoadDBInMemory;
fdqVilles.Active := True;
end;
end;
end. |