From 83108d28c57be88156dfd08fee20955f1d007ccd Mon Sep 17 00:00:00 2001 From: Ansgar Becker Date: Sun, 22 Mar 2020 14:00:52 +0100 Subject: [PATCH] Issue #946: support multiple SQLite database files per session definition, in field "Database file(s)". Use the first one as main file, and attach further files. --- out/locale/en/LC_MESSAGES/default.po | 11 +++++- source/connections.dfm | 20 +++++++++- source/connections.pas | 55 +++++++++++++++++----------- source/dbconnection.pas | 21 +++++++++-- 4 files changed, 78 insertions(+), 29 deletions(-) diff --git a/out/locale/en/LC_MESSAGES/default.po b/out/locale/en/LC_MESSAGES/default.po index 9fde0e31..bd5f07bf 100644 --- a/out/locale/en/LC_MESSAGES/default.po +++ b/out/locale/en/LC_MESSAGES/default.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: HeidiSQL\n" "POT-Creation-Date: 2012-11-05 21:40\n" -"PO-Revision-Date: 2020-02-25 21:25+0100\n" +"PO-Revision-Date: 2020-03-22 13:56+0100\n" "Last-Translator: Ansgar Becker \n" "Language-Team: English (http://www.transifex.com/projects/p/heidisql/language/en/)\n" "MIME-Version: 1.0\n" @@ -282,6 +282,9 @@ msgstr "Password:" msgid "Hostname / IP:" msgstr "Hostname / IP:" +msgid "Database filename(s)" +msgstr "Database filename(s)" + #. connform..PageControlDetails..tabSettings..lblUsername..Caption #: connections.dfm:261 msgid "User:" @@ -6423,3 +6426,9 @@ msgstr "Open URL" msgid "Open URL in your webbrowser" msgstr "Open URL in your webbrowser" + +msgid "Find database files..." +msgstr "Find database files..." + +msgid "Add database files..." +msgstr "Add database files..." diff --git a/source/connections.dfm b/source/connections.dfm index 99683ccc..3f6ab205 100644 --- a/source/connections.dfm +++ b/source/connections.dfm @@ -266,12 +266,13 @@ object connform: Tconnform Height = 21 Anchors = [akLeft, akTop, akRight] Images = MainForm.VirtualImageListMain - RightButton.ImageIndex = 51 + RightButton.DropDownMenu = popupHost + RightButton.ImageIndex = 75 + RightButton.Visible = True TabOrder = 2 OnChange = editHostChange OnDblClick = editHostDblClick OnExit = editTrim - OnRightButtonClick = PickFile end object comboNetType: TComboBox Left = 120 @@ -1054,4 +1055,19 @@ object connform: Tconnform Left = 112 Top = 144 end + object popupHost: TPopupMenu + Images = MainForm.VirtualImageListMain + Left = 24 + Top = 208 + object menuFindDatabaseFiles: TMenuItem + Caption = 'Find database files...' + ImageIndex = 30 + OnClick = FindAddDatabaseFilesClick + end + object menuAddDatabaseFiles: TMenuItem + Caption = 'Add database files...' + ImageIndex = 72 + OnClick = FindAddDatabaseFilesClick + end + end end diff --git a/source/connections.pas b/source/connections.pas index a5863d80..a90479c3 100644 --- a/source/connections.pas +++ b/source/connections.pas @@ -122,6 +122,9 @@ type pnlLeft: TPanel; ListSessions: TVirtualStringTree; editSearch: TButtonedEdit; + popupHost: TPopupMenu; + menuFindDatabaseFiles: TMenuItem; + menuAddDatabaseFiles: TMenuItem; procedure FormCreate(Sender: TObject); procedure btnOpenClick(Sender: TObject); procedure FormShow(Sender: TObject); @@ -179,6 +182,7 @@ type procedure editHostDblClick(Sender: TObject); procedure ListSessionsNodeDblClick(Sender: TBaseVirtualTree; const HitInfo: THitInfo); + procedure FindAddDatabaseFilesClick(Sender: TObject); private { Private declarations } FLoaded: Boolean; @@ -363,21 +367,10 @@ procedure Tconnform.btnOpenClick(Sender: TObject); var Connection: TDBConnection; Params: TConnectionParameters; - Msg: String; - DoCreateDb: Integer; begin // Connect to selected session Params := CurrentParams; - if (Params.NetType = ntSQLite) - and (not FileExists(Params.Hostname)) - then begin - Msg := f_('Database file "%s" does not exist. Shall it be created now?', [Params.Hostname]); - DoCreateDb := MessageDialog(Msg, mtConfirmation, [mbNo, mbYes]); - if DoCreateDb = mrNo then - Exit; - end; - if not btnOpen.Enabled then Exit; btnOpen.Enabled := False; @@ -1274,6 +1267,20 @@ begin end; +procedure Tconnform.FindAddDatabaseFilesClick(Sender: TObject); +var + PrevText: String; +begin + // Append or replace filenames + PrevText := editHost.Text; + PickFile(editHost); + if (Sender = menuAddDatabaseFiles) + and (not PrevText.IsEmpty) + and (editHost.Text <> '') then begin + editHost.Text := PrevText + DELIM + editHost.Text; + end; +end; + procedure Tconnform.ValidateControls; var SessionFocused, FolderFocused: Boolean; @@ -1293,7 +1300,7 @@ begin lblHost.Caption := _('Socket name:'); end; ntSQLite: begin - lblHost.Caption := _('Database filename')+':'; + lblHost.Caption := _('Database filename(s)')+':'; end else begin lblHost.Caption := _('Hostname / IP:'); @@ -1383,14 +1390,17 @@ var Edit: TButtonedEdit; i: Integer; Control: TControl; + FileNames: TStringList; begin // Select startup SQL file, SSL file or whatever button clicked Edit := Sender as TButtonedEdit; Selector := TOpenDialog.Create(Self); Selector.FileName := editStartupScript.Text; - if Edit = editHost then - Selector.Filter := 'SQLite databases (*.sqlite3;*.sqlite;*.db;*.s3db)|*.sqlite3;*.sqlite;*.db;*.s3db|'+_('All files')+' (*.*)|*.*' - else if Edit = editStartupScript then + if Edit = editHost then begin + Selector.Filter := 'SQLite databases (*.sqlite3;*.sqlite;*.db;*.s3db)|*.sqlite3;*.sqlite;*.db;*.s3db|'+_('All files')+' (*.*)|*.*'; + Selector.Options := Selector.Options - [ofFileMustExist]; + Selector.Options := Selector.Options + [ofAllowMultiSelect]; + end else if Edit = editStartupScript then Selector.Filter := _('SQL files')+' (*.sql)|*.sql|'+_('All files')+' (*.*)|*.*' else if Edit = editSSHPlinkExe then Selector.Filter := _('Executables')+' (*.exe)|*.exe|'+_('All files')+' (*.*)|*.*' @@ -1406,15 +1416,16 @@ begin break; end; end; - if Edit = editHost then - Selector.Options := Selector.Options - [ofFileMustExist]; if Selector.Execute then begin - // Remove path if it's the application directory - if ExtractFilePath(Selector.FileName) = ExtractFilePath(Application.ExeName) then - Edit.Text := ExtractFileName(Selector.FileName) - else - Edit.Text := Selector.FileName; + FileNames := TStringList.Create; + FileNames.Assign(Selector.Files); + for i:=0 to FileNames.Count-1 do begin + // Remove path if it's the application directory + if ExtractFilePath(FileNames[i]) = ExtractFilePath(Application.ExeName) then + FileNames[i] := ExtractFileName(FileNames[i]); + end; + Edit.Text := implodestr(DELIM, FileNames); Modification(Selector); end; Selector.Free; diff --git a/source/dbconnection.pas b/source/dbconnection.pas index d4ddd1de..2df1ed60 100644 --- a/source/dbconnection.pas +++ b/source/dbconnection.pas @@ -2444,20 +2444,33 @@ procedure TSQLiteConnection.SetActive(Value: Boolean); var ConnectResult: Integer; tmpdb: String; + FileNames: TStringList; + MainFile, DbAlias: String; + i: Integer; begin + // Support multiple filenames, and use first one as main database + FileNames := Explode(DELIM, Parameters.Hostname); + MainFile := IfThen(FileNames.Count>=1, FileNames[0], ''); + if Value then begin DoBeforeConnect; + ConnectResult := FLib.sqlite3_open( - PAnsiChar(Utf8Encode(Parameters.Hostname)), + PAnsiChar(Utf8Encode(MainFile)), FHandle); if ConnectResult = SQLITE_OK then begin FActive := True; + Log(lcInfo, f_('Connected. Thread-ID: %d', [ThreadId])); + FIsUnicode := True; + // Attach additional databases + for i:=1 to FileNames.Count-1 do begin + DbAlias := TPath.GetFileNameWithoutExtension(FileNames[i]); + Query('ATTACH DATABASE '+EscapeString(FileNames[i])+' AS '+QuoteIdent(DbAlias)); + end; FServerDateTimeOnStartup := GetVar('SELECT DATETIME()'); FServerVersionUntouched := GetVar('SELECT sqlite_version()'); FConnectionStarted := GetTickCount div 1000; - Log(lcInfo, f_('Connected. Thread-ID: %d', [ThreadId])); - FIsUnicode := True; FServerUptime := -1; DoAfterConnect; @@ -2484,7 +2497,7 @@ begin FLib.sqlite3_close(FHandle); FHandle := nil; FActive := False; - Log(lcInfo, f_(MsgDisconnect, [FParameters.Hostname, DateTimeToStr(Now)])); + Log(lcInfo, f_(MsgDisconnect, [MainFile, DateTimeToStr(Now)])); end; end; end;