В чём ошибка при подключении из Delphi к существующей БД SQLite3 Multiple Ciphers?
Про подключение библиотеки SQLite3 Multiple Ciphers написано здесь. Пытаюсь подключиться к уже созданной БД, но получаю ошибку при подключении:
Project Project1.exe raised exception class ESQLiteNativeException with message '[FireDAC][Phys][SQLite] ERROR: file is not a database'.
Вот полный код создания и подключения к БД:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, FireDAC.Stan.Intf, FireDAC.Stan.Option,
FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def,
FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys, FireDAC.Stan.Param,
FireDAC.DatS, FireDAC.DApt.Intf, FireDAC.DApt, FireDAC.VCLUI.Wait,
FireDAC.Stan.ExprFuncs,
FireDAC.Phys.SQLiteDef, FireDAC.Phys.SQLite, FireDAC.Comp.UI,
FireDAC.Comp.Client, Data.DB, FireDAC.Comp.DataSet,
FireDAC.Phys.SQLiteWrapper.Stat;
type
TForm1 = class(TForm)
FDConnection1: TFDConnection;
FDTransaction1: TFDTransaction;
FDQuery1: TFDQuery;
FDGUIxWaitCursor1: TFDGUIxWaitCursor;
FDPhysSQLiteDriverLink1: TFDPhysSQLiteDriverLink;
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure ConnectWithSqlite3Dll;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TForm1 }
procedure TForm1.FormShow(Sender: TObject);
begin
ConnectWithSqlite3Dll;
end;
procedure TForm1.ConnectWithSqlite3Dll;
const
LIB_NAME = 'sqlite3mc_icu.dll';
DB_NAME = 'test.db';
// наименование dll и порядок важен!
ICU_DLLs: array[0..4] of String = (
'icudt77.dll',
'icuuc77.dll',
'icuin77.dll',
'icuio77.dll',
'icutu77.dll'
);
var
hDll: HMODULE;
LibPath, icu, res, Version: string;
begin
LibPath := ExtractFilePath(ParamStr(0)) + 'libs\';
//загрузка необходимых библиотек
for icu in ICU_DLLs do
begin
hDll := LoadLibrary(PChar(LibPath + icu));
if hDll = 0 then
raise Exception.Create('Не удалось загрузить: ' + icu);
end;
// Настраиваем драйвер
FDPhysSQLiteDriverLink1.DriverID := 'SQLite';
FDPhysSQLiteDriverLink1.VendorLib := LibPath + LIB_NAME;
// Альтернативный способ указания динамической библиотеки
FDConnection1.Params.Clear;
FDConnection1.Params.DriverID := 'SQLite';
FDConnection1.Params.Database := DB_NAME;
if not FileExists(DB_NAME) then
begin
// создание БД с шифрованием
FDConnection1.ExecSQL('PRAGMA cipher=''aes256cbc''');
FDConnection1.ExecSQL('PRAGMA kdf_iter=256000');
FDConnection1.ExecSQL('PRAGMA key=''123''');
FDQuery1.SQL.Clear;
FDQuery1.SQL.Text := 'CREATE TABLE goods ('
+ 'id INTEGER PRIMARY KEY AUTOINCREMENT, good TEXT)';
FDQuery1.ExecSQL;
FDQuery1.SQL.Clear;
FDQuery1.SQL.Text:='insert into goods (id, good) values (3, ''диван'')';
FDQuery1.ExecSQL;
end
else
begin
// подключение к созданной БД
// здесь получаю ошибку
//"Project Project1.exe raised exception class ESQLiteNativeException
// with message '[FireDAC][Phys][SQLite] ERROR: file is not a database'."
FDConnection1.ExecSQL('PRAGMA cipher=''aes256cbc''');
FDConnection1.ExecSQL('PRAGMA key=''123''');
end;
FDQuery1.SQL.Clear;
FDQuery1.SQL.Text:='select good from goods where id = 3';
FDQuery1.Open;
res:=FDQuery1.FieldByName('good').AsString;
// Проверка версии
FDQuery1.SQL.Clear;
FDQuery1.SQL.Text := 'SELECT sqlite_version() AS version';
FDQuery1.Open;
Version:=FDQuery1.FieldByName('version').AsString;
ShowMessage('SQLite version: ' + Version + #13 + 'Результат: ' + res);
end;
end.
Ошибку получаю в ветке else на строке:
FDConnection1.ExecSQL('PRAGMA cipher=''aes256cbc''');
В чём ошибка?
Ответы (1 шт):
Автор решения: golubtsoff
→ Ссылка
Отвечу сам себе. Вместо способа подключения с помощью "Pragma ..." следует использовать строку URI. Для тестового примера из вопроса выглядит это так:
FDConnection1.Params.Values['Database'] :='file:test.db?cipher=aes256cbc&key=123';
FDConnection1.Open;