diff --git a/source/connections.dfm b/source/connections.dfm index 99423b70..0fa61795 100644 --- a/source/connections.dfm +++ b/source/connections.dfm @@ -4,10 +4,10 @@ object connform: Tconnform Top = 129 BorderIcons = [biSystemMenu] Caption = 'Session manager' - ClientHeight = 274 + ClientHeight = 294 ClientWidth = 494 Color = clBtnFace - Constraints.MinHeight = 310 + Constraints.MinHeight = 330 Constraints.MinWidth = 510 Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText @@ -25,7 +25,7 @@ object connform: Tconnform OnShow = FormShow DesignSize = ( 494 - 274) + 294) PixelsPerInch = 96 TextHeight = 13 object lblSession: TLabel @@ -49,7 +49,7 @@ object connform: Tconnform end object btnSave: TButton Left = 64 - Top = 241 + Top = 261 Width = 50 Height = 25 Anchors = [akLeft, akBottom] @@ -60,7 +60,7 @@ object connform: Tconnform object btnOpen: TButton Tag = 15 Left = 320 - Top = 241 + Top = 261 Width = 80 Height = 25 Anchors = [akRight, akBottom] @@ -73,7 +73,7 @@ object connform: Tconnform object btnCancel: TButton Tag = 16 Left = 406 - Top = 241 + Top = 261 Width = 80 Height = 25 Anchors = [akRight, akBottom] @@ -86,7 +86,7 @@ object connform: Tconnform Left = 9 Top = 27 Width = 162 - Height = 206 + Height = 226 Anchors = [akLeft, akTop, akBottom] EditDelay = 250 Header.AutoSizeIndex = 0 @@ -121,7 +121,7 @@ object connform: Tconnform end object btnNew: TButton Left = 8 - Top = 241 + Top = 261 Width = 50 Height = 25 Anchors = [akLeft, akBottom] @@ -131,7 +131,7 @@ object connform: Tconnform end object btnDelete: TButton Left = 120 - Top = 241 + Top = 261 Width = 50 Height = 25 Anchors = [akLeft, akBottom] @@ -143,7 +143,7 @@ object connform: Tconnform Left = 177 Top = 8 Width = 309 - Height = 226 + Height = 246 ActivePage = tabSettings Anchors = [akLeft, akTop, akRight, akBottom] Images = MainForm.ImageListMain @@ -153,10 +153,10 @@ object connform: Tconnform ImageIndex = 39 DesignSize = ( 301 - 197) + 217) object lblStartupScript: TLabel Left = 3 - Top = 168 + Top = 193 Width = 69 Height = 13 Caption = 'Startup script:' @@ -205,16 +205,23 @@ object connform: Tconnform Height = 13 Caption = 'Network type:' end + object lblDatabase: TLabel + Left = 3 + Top = 168 + Width = 55 + Height = 13 + Caption = 'Databases:' + end object editStartupScript: TButtonedEdit Left = 101 - Top = 165 + Top = 190 Width = 197 Height = 21 Anchors = [akLeft, akTop, akRight] Images = MainForm.ImageListMain RightButton.ImageIndex = 51 RightButton.Visible = True - TabOrder = 6 + TabOrder = 8 OnChange = Modification OnDblClick = PickFile OnRightButtonClick = PickFile @@ -227,7 +234,7 @@ object connform: Tconnform Height = 17 Anchors = [akLeft, akTop, akRight] Caption = 'Compressed client/server protocol' - TabOrder = 5 + TabOrder = 6 OnClick = Modification end object editPort: TEdit @@ -235,7 +242,7 @@ object connform: Tconnform Top = 117 Width = 60 Height = 21 - TabOrder = 3 + TabOrder = 4 Text = '0' OnChange = editPortChange end @@ -245,7 +252,7 @@ object connform: Tconnform Width = 17 Height = 21 Max = 32767 - TabOrder = 4 + TabOrder = 5 Thousands = False OnChangingEx = updownPortChangingEx end @@ -256,7 +263,7 @@ object connform: Tconnform Height = 21 Anchors = [akLeft, akTop, akRight] PasswordChar = '*' - TabOrder = 2 + TabOrder = 3 OnChange = Modification end object editUsername: TEdit @@ -265,7 +272,7 @@ object connform: Tconnform Width = 197 Height = 21 Anchors = [akLeft, akTop, akRight] - TabOrder = 1 + TabOrder = 2 OnChange = Modification end object editHost: TEdit @@ -274,7 +281,7 @@ object connform: Tconnform Width = 197 Height = 21 Anchors = [akLeft, akTop, akRight] - TabOrder = 0 + TabOrder = 1 OnChange = editHostChange end object comboNetType: TComboBox @@ -285,7 +292,7 @@ object connform: Tconnform Style = csDropDownList Anchors = [akLeft, akTop, akRight] ItemIndex = 0 - TabOrder = 7 + TabOrder = 0 Text = 'TCP/IP' OnChange = Modification Items.Strings = ( @@ -293,13 +300,24 @@ object connform: Tconnform 'Named pipe' 'SSH tunnel') end + object comboDatabases: TComboBox + Left = 101 + Top = 165 + Width = 197 + Height = 21 + Anchors = [akLeft, akTop, akRight] + TabOrder = 7 + TextHint = 'Separated by semicolon' + OnChange = Modification + OnDropDown = comboDatabasesDropDown + end end object tabSSHtunnel: TTabSheet Caption = 'SSH tunnel' ImageIndex = 147 DesignSize = ( 301 - 197) + 217) object lblSSHLocalPort: TLabel Left = 3 Top = 163 @@ -456,7 +474,7 @@ object connform: Tconnform ImageIndex = 144 DesignSize = ( 301 - 197) + 217) object lblSSLPrivateKey: TLabel Tag = 6 Left = 3 @@ -532,7 +550,7 @@ object connform: Tconnform ImageIndex = 145 DesignSize = ( 301 - 197) + 217) object lblLastConnectLeft: TLabel Left = 3 Top = 31 diff --git a/source/connections.pas b/source/connections.pas index c0aa5220..f8aab5d1 100644 --- a/source/connections.pas +++ b/source/connections.pas @@ -73,6 +73,8 @@ type editSSHPrivateKey: TButtonedEdit; lblSSHkeyfile: TLabel; lblDownloadPlink: TLabel; + comboDatabases: TComboBox; + lblDatabase: TLabel; procedure FormCreate(Sender: TObject); procedure btnOpenClick(Sender: TObject); procedure FormShow(Sender: TObject); @@ -107,6 +109,7 @@ type procedure editSSHPlinkExeChange(Sender: TObject); procedure editHostChange(Sender: TObject); procedure lblDownloadPlinkClick(Sender: TObject); + procedure comboDatabasesDropDown(Sender: TObject); private { Private declarations } FLoaded: Boolean; @@ -115,6 +118,7 @@ type FOrgParams: TConnectionParameters; FWidthListSessions: Byte; // Percentage values function SelectedSession: String; + function CurrentParams: TConnectionParameters; procedure SessionNamesChange(Sender: TObject); procedure RefreshSessionList; procedure FinalizeModifications(var CanProceed: Boolean); @@ -197,35 +201,12 @@ end; procedure Tconnform.btnOpenClick(Sender: TObject); -var - Params: TConnectionParameters; begin // Connect to selected session Screen.Cursor := crHourglass; - Params := TConnectionParameters.Create; - Params.NetType := TNetType(comboNetType.ItemIndex); - Params.Hostname := editHost.Text; - Params.Username := editUsername.Text; - Params.Password := editPassword.Text; - Params.Port := MakeInt(editPort.Text); - Params.SSHHost := editSSHHost.Text; - Params.SSHPort := MakeInt(editSSHPort.Text); - Params.SSHUser := editSSHuser.Text; - Params.SSHPassword := editSSHpassword.Text; - Params.SSHPrivateKey := editSSHPrivateKey.Text; - Params.SSHLocalPort := MakeInt(editSSHlocalport.Text); - Params.SSHPlinkExe := editSSHplinkexe.Text; - Params.SSLPrivateKey := editSSLPrivateKey.Text; - Params.SSLCertificate := editSSLCertificate.Text; - Params.SSLCACertificate := editSSLCACertificate.Text; - Params.StartupScriptFilename := editStartupScript.Text; - if chkCompressed.Checked then - Params.Options := Params.Options + [opCompress] - else - Params.Options := Params.Options - [opCompress]; - if Mainform.InitConnection(Params, SelectedSession) then begin - ModalResult := mrOK; - end else begin + if Mainform.InitConnection(CurrentParams, SelectedSession) then + ModalResult := mrOK + else begin TimerStatistics.OnTimer(Sender); ModalResult := mrNone; end; @@ -242,6 +223,7 @@ begin MainReg.WriteString(REGNAME_PORT, editPort.Text); MainReg.WriteInteger(REGNAME_NETTYPE, comboNetType.ItemIndex); MainReg.WriteBool(REGNAME_COMPRESSED, chkCompressed.Checked); + MainReg.WriteString(REGNAME_DATABASES, comboDatabases.Text); MainReg.WriteString(REGNAME_STARTUPSCRIPT, editStartupScript.Text); MainReg.WriteString(REGNAME_SSHHOST, editSSHHost.Text); MainReg.WriteInteger(REGNAME_SSHPORT, MakeInt(editSSHport.Text)); @@ -352,6 +334,34 @@ begin end; +function Tconnform.CurrentParams: TConnectionParameters; +begin + // Return non-stored parameters + Result := TConnectionParameters.Create; + Result.NetType := TNetType(comboNetType.ItemIndex); + Result.Hostname := editHost.Text; + Result.Username := editUsername.Text; + Result.Password := editPassword.Text; + Result.Port := MakeInt(editPort.Text); + Result.AllDatabases := comboDatabases.Text; + Result.SSHHost := editSSHHost.Text; + Result.SSHPort := MakeInt(editSSHPort.Text); + Result.SSHUser := editSSHuser.Text; + Result.SSHPassword := editSSHpassword.Text; + Result.SSHPrivateKey := editSSHPrivateKey.Text; + Result.SSHLocalPort := MakeInt(editSSHlocalport.Text); + Result.SSHPlinkExe := editSSHplinkexe.Text; + Result.SSLPrivateKey := editSSLPrivateKey.Text; + Result.SSLCertificate := editSSLCertificate.Text; + Result.SSLCACertificate := editSSLCACertificate.Text; + Result.StartupScriptFilename := editStartupScript.Text; + if chkCompressed.Checked then + Result.Options := Result.Options + [opCompress] + else + Result.Options := Result.Options - [opCompress]; +end; + + procedure Tconnform.SessionNamesChange(Sender: TObject); begin ListSessions.RootNodeCount := (Sender as TStringlist).Count; @@ -429,6 +439,7 @@ begin editPassword.Text := FOrgParams.Password; editPort.Text := IntToStr(FOrgParams.Port); chkCompressed.Checked := opCompress in FOrgParams.Options; + comboDatabases.Text := FOrgParams.AllDatabases; editStartupScript.Text := FOrgParams.StartupScriptFilename; editSSHPlinkExe.Text := FOrgParams.SSHPlinkExe; editSSHHost.Text := FOrgParams.SSHHost; @@ -564,6 +575,28 @@ begin end; +procedure Tconnform.comboDatabasesDropDown(Sender: TObject); +var + Connection: TMySQLConnection; +begin + // Try to connect and lookup database names + Connection := TMySQLConnection.Create(Self); + Connection.Parameters := CurrentParams; + Connection.LogPrefix := '['+SelectedSession+'] '; + Connection.OnLog := Mainform.LogSQL; + comboDatabases.Items.Clear; + Screen.Cursor := crHourglass; + try + Connection.Active := True; + comboDatabases.Items := Connection.GetCol('SHOW DATABASES'); + except + // Silence connection errors here - should be sufficient to log them + end; + FreeAndNil(Connection); + Screen.Cursor := crDefault; +end; + + procedure Tconnform.Modification(Sender: TObject); var PasswordModified: Boolean; @@ -576,6 +609,7 @@ begin or ((opCompress in FOrgParams.Options) <> chkCompressed.Checked) or (FOrgParams.NetType <> TNetType(comboNetType.ItemIndex)) or (FOrgParams.StartupScriptFilename <> editStartupScript.Text) + or (FOrgParams.AllDatabases <> comboDatabases.Text) or (FOrgParams.SSHHost <> editSSHHost.Text) or (IntToStr(FOrgParams.SSHPort) <> editSSHPort.Text) or (FOrgParams.SSHPlinkExe <> editSSHPlinkExe.Text) diff --git a/source/const.inc b/source/const.inc index b09ff1c1..153d4dd3 100644 --- a/source/const.inc +++ b/source/const.inc @@ -137,7 +137,7 @@ const REGNAME_COMPRESSED = 'Compressed'; DEFAULT_COMPRESSED = False; REGNAME_STARTUPSCRIPT = 'StartupScriptFilename'; - REGNAME_ONLYDBS = 'OnlyDBs'; + REGNAME_DATABASES = 'Databases'; REGNAME_EXP_CREATEDB = 'ExportSQL_CreateDatabases'; REGNAME_EXP_DROPDB = 'ExportSQL_DropDatabases'; REGNAME_EXP_CREATETABLE = 'ExportSQL_CreateTables'; diff --git a/source/copytable.pas b/source/copytable.pas index 4cdf329c..2fe61a88 100644 --- a/source/copytable.pas +++ b/source/copytable.pas @@ -106,7 +106,7 @@ begin // Select TargetDatabase ComboSelectDatabase.Items.Clear; - ComboSelectDatabase.Items.Assign(Mainform.Databases); + ComboSelectDatabase.Items.Assign(Mainform.AllDatabases); ComboSelectDatabase.ItemIndex := ComboSelectDatabase.Items.IndexOf( Mainform.ActiveDatabase ); if comboSelectDatabase.ItemIndex = -1 then comboSelectDatabase.ItemIndex := 0; diff --git a/source/createdatabase.pas b/source/createdatabase.pas index 6b6a583d..9cb37ff1 100644 --- a/source/createdatabase.pas +++ b/source/createdatabase.pas @@ -203,7 +203,8 @@ end; procedure TCreateDatabaseForm.btnOKClick(Sender: TObject); var sql : String; - AllDatabases, Unions, ObjectsLeft: TStringList; + AllDatabases: TStringList; + ObjectsLeft: TDBObjectList; ObjectsInNewDb, ObjectsInOldDb: TDBObjectList; i, j: Integer; begin @@ -272,24 +273,13 @@ begin Mainform.Connection.ClearDbObjects(modifyDB); Mainform.Connection.ClearDbObjects(editDBName.Text); end; - // Last step for renaming: drop source database - ObjectsLeft := TStringList.Create; - // Last check if old db is really empty, before we drop it. Especially triggers need to be checked. - Unions := TStringList.Create; - if Mainform.Connection.InformationSchemaObjects.IndexOf('TABLES') > -1 then - Unions.Add('SELECT 1 FROM '+Mainform.mask(DBNAME_INFORMATION_SCHEMA)+'.TABLES WHERE TABLE_SCHEMA='+esc(modifyDB)); - if Mainform.Connection.InformationSchemaObjects.IndexOf('ROUTINES') > -1 then - Unions.Add('SELECT 1 FROM '+Mainform.mask(DBNAME_INFORMATION_SCHEMA)+'.ROUTINES WHERE ROUTINE_SCHEMA='+esc(modifyDB)); - if Mainform.Connection.InformationSchemaObjects.IndexOf('TRIGGERS') > -1 then - Unions.Add('SELECT 1 FROM '+Mainform.mask(DBNAME_INFORMATION_SCHEMA)+'.TRIGGERS WHERE TRIGGER_SCHEMA='+esc(modifyDB)); - if Unions.Count = 1 then - ObjectsLeft := Mainform.Connection.GetCol(Unions[0]) - else if Unions.Count > 1 then - ObjectsLeft := Mainform.Connection.GetCol('(' + implodestr(') UNION (', Unions) + ')'); + // Last check if old db is really empty, before we drop it. + ObjectsLeft := Mainform.Connection.GetDBObjects(modifyDB); if ObjectsLeft.Count = 0 then begin Mainform.Connection.Query('DROP DATABASE '+Mainform.mask(modifyDB)); + InvalidateVT(Mainform.DBtree, VTREE_NOTLOADED_PURGECACHE, False); + Mainform.ActiveDatabase := ''; end; - FreeAndNil(ObjectsLeft); end; // Close form ModalResult := mrOK; @@ -298,6 +288,19 @@ begin MessageDlg( 'Altering database "'+editDBName.Text+'" failed:'+CRLF+CRLF+E.Message, mtError, [mbOK], 0 ); // Keep form open end; + + // Save new db name to registry + AllDatabases := Explode(';', Mainform.Connection.Parameters.AllDatabases); + if AllDatabases.Count > 0 then begin + i := AllDatabases.IndexOf(modifyDB); + if i > -1 then + AllDatabases[i] := editDBname.Text + else + AllDatabases.Add(editDBname.Text); + OpenRegistry(Mainform.SessionName); + Mainform.Connection.Parameters.AllDatabases := ImplodeStr(';', AllDatabases); + MainReg.WriteString(REGNAME_DATABASES, Mainform.Connection.Parameters.AllDatabases); + end; end; diff --git a/source/helpers.pas b/source/helpers.pas index c437c106..db70ab71 100644 --- a/source/helpers.pas +++ b/source/helpers.pas @@ -3513,10 +3513,16 @@ begin if not Assigned(VT) then Exit; VT.Tag := RefreshTag; - if ImmediateRepaint then - VT.Repaint - else - VT.Invalidate; + if VT = Mainform.DBtree then begin + VT.ResetNode(VT.GetFirst); + if ImmediateRepaint then + VT.ReinitNode(VT.GetFirst, False); + end else begin + if ImmediateRepaint then + VT.Repaint + else + VT.Invalidate; + end; end; @@ -3670,6 +3676,7 @@ begin Result.Username := GetRegValue(REGNAME_USER, '', Session); Result.Password := decrypt(GetRegValue(REGNAME_PASSWORD, '', Session)); Result.Port := StrToIntDef(GetRegValue(REGNAME_PORT, '', Session), DEFAULT_PORT); + Result.AllDatabases := GetRegValue(REGNAME_DATABASES, '', Session); Result.SSHHost := GetRegValue(REGNAME_SSHHOST, '', Session); Result.SSHPort := GetRegValue(REGNAME_SSHPORT, DEFAULT_SSHPORT, Session); Result.SSHUser := GetRegValue(REGNAME_SSHUSER, '', Session); diff --git a/source/insertfiles.pas b/source/insertfiles.pas index f78263d3..df6e3947 100644 --- a/source/insertfiles.pas +++ b/source/insertfiles.pas @@ -79,7 +79,7 @@ procedure TfrmInsertFiles.FormShow(Sender: TObject); begin Caption := Mainform.SessionName + ' - Insert files into table ...'; ComboBoxDBs.Items.Clear; - ComboBoxDBs.Items.Assign(Mainform.Databases); + ComboBoxDBs.Items.Assign(Mainform.AllDatabases); ComboBoxDBs.ItemIndex := ComboBoxDBs.Items.IndexOf( Mainform.ActiveDatabase ); if ComboBoxDBs.ItemIndex = -1 then ComboBoxDBs.ItemIndex := 0; diff --git a/source/loaddata.pas b/source/loaddata.pas index e54ccc38..21da695a 100644 --- a/source/loaddata.pas +++ b/source/loaddata.pas @@ -120,7 +120,7 @@ procedure Tloaddataform.FormShow(Sender: TObject); begin // read dbs and Tables from treeview comboDatabase.Items.Clear; - comboDatabase.Items.Assign(Mainform.Databases); + comboDatabase.Items.Assign(Mainform.AllDatabases); comboDatabase.ItemIndex := comboDatabase.Items.IndexOf( Mainform.ActiveDatabase ); if comboDatabase.ItemIndex = -1 then comboDatabase.ItemIndex := 0; diff --git a/source/main.dfm b/source/main.dfm index 96f4cbe3..3c1621aa 100644 --- a/source/main.dfm +++ b/source/main.dfm @@ -405,30 +405,6 @@ object MainForm: TMainForm WideText = 'Size' end> end - object comboOnlyDBs: TComboBox - AlignWithMargins = True - Left = 0 - Top = 336 - Width = 169 - Height = 21 - Hint = - 'Database filter|A list of databases, separated by semicolon. Can' + - ' contain regular expressions, e.g. "mydb;test.*;project\d+".' - Margins.Left = 0 - Margins.Top = 0 - Margins.Right = 0 - Margins.Bottom = 0 - Align = alBottom - ParentShowHint = False - ShowHint = True - TabOrder = 1 - TextHint = 'Database filter' - OnChange = comboOnlyDBsChange - OnDragDrop = comboOnlyDBsDragDrop - OnDragOver = comboOnlyDBsDragOver - OnExit = comboOnlyDBsExit - OnKeyDown = comboOnlyDBsKeyDown - end end object pnlRight: TPanel Left = 173 diff --git a/source/main.pas b/source/main.pas index fb79ee50..19ffbb16 100644 --- a/source/main.pas +++ b/source/main.pas @@ -202,7 +202,6 @@ type panelTop: TPanel; pnlLeft: TPanel; DBtree: TVirtualStringTree; - comboOnlyDBs: TComboBox; Splitter1: TSplitter; PageControlMain: TPageControl; tabData: TTabSheet; @@ -716,12 +715,6 @@ type function IsQueryTab(PageIndex: Integer; IncludeFixed: Boolean): Boolean; procedure popupMainTabsPopup(Sender: TObject); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); - procedure comboOnlyDBsChange(Sender: TObject); - procedure comboOnlyDBsExit(Sender: TObject); - procedure comboOnlyDBsDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; - var Accept: Boolean); - procedure comboOnlyDBsDragDrop(Sender, Source: TObject; X, Y: Integer); - procedure comboOnlyDBsKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure actFilterPanelExecute(Sender: TObject); procedure TimerFilterVTTimer(Sender: TObject); procedure PageControlMainContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean); @@ -812,7 +805,6 @@ type SessionName: String; AllDatabases: TStringList; AllDatabasesDetails: TMySQLQuery; - Databases: TStringList; btnAddTab: TSpeedButton; QueryTabs: TObjectList; DBObjectsMaxSize: Int64; @@ -1338,6 +1330,7 @@ begin // SynMemo font, hightlighting and shortcuts SetupSynEditors; + AllDatabases := TStringList.Create; DataGridResult := TGridResult.Create; btnAddTab := TSpeedButton.Create(PageControlMain); @@ -1601,17 +1594,6 @@ begin Mainreg.WriteInteger(REGNAME_SERVERVERSION, Connection.ServerVersionInt); Mainreg.WriteString(REGNAME_LASTCONNECT, DateTimeToStr(Now)); - comboOnlyDBs.Items.Text := GetRegValue(REGNAME_ONLYDBS, '', SessionName); - if comboOnlyDBs.Items.Count > 0 then - comboOnlyDBs.ItemIndex := 0 - else - comboOnlyDBs.Text := ''; - - // Remove db and table nodes, force host node to initialize again - DBtree.ResetNode(DBTree.GetFirst); - - DBTree.Color := GetRegValue(REGNAME_TREEBACKGROUND, clWindow, SessionName); - // Process startup script StartupScript := Trim(Connection.Parameters.StartupScriptFilename); if StartupScript <> '' then begin @@ -1629,6 +1611,10 @@ begin end; end; + // Remove db and table nodes, force host node to initialize again + InvalidateVT(DBtree, VTREE_NOTLOADED_PURGECACHE, False); + DBTree.Color := GetRegValue(REGNAME_TREEBACKGROUND, clWindow, SessionName); + // Reselect last used database if GetRegValue( REGNAME_RESTORELASTUSEDDB, DEFAULT_RESTORELASTUSEDDB ) then begin lastUsedDB := GetRegValue(REGNAME_LASTUSEDDB, '', SessionName); @@ -1708,7 +1694,6 @@ begin // relative from already opened folder! OpenRegistry(SessionName); MainReg.WriteString( REGNAME_LASTUSEDDB, Connection.Database ); - MainReg.WriteString( REGNAME_ONLYDBS, comboOnlyDBs.Items.Text ); // Post pending UPDATE if DataGridHasChanges then @@ -1718,7 +1703,6 @@ begin DBtree.ClearSelection; DBtree.FocusedNode := nil; PreviousFocusedNode := nil; - FreeAndNil(AllDatabases); FreeAndNil(AllDatabasesDetails); FreeAndNil(DataGridHiddenColumns); SynMemoFilter.Clear; @@ -1743,8 +1727,6 @@ end; procedure TMainForm.actCreateDatabaseExecute(Sender: TObject); -var - newdb: String; begin // Create database: // Create modal form once on demand @@ -1753,17 +1735,7 @@ begin // Rely on the modalresult being set correctly if CreateDatabaseForm.ShowModal = mrOK then - begin - newdb := CreateDatabaseForm.editDBName.Text; - // Add new DB to database filter if it's not empty - if comboOnlyDBs.Text <> '' then begin - comboOnlyDBs.Text := comboOnlyDBs.Text + ';' + newdb; - comboOnlyDBs.Items.Insert(0, comboOnlyDBs.Text); - end; - FreeAndNil(AllDatabases); - // reload db nodes and switch to new one - RefreshTree(False, newdb); - end; + InvalidateVT(DBtree, VTREE_NOTLOADED_PURGECACHE, False); end; @@ -2261,12 +2233,9 @@ begin Abort; try Connection.Query('DROP DATABASE ' + mask(activeDB)); - Node := DBTree.FocusedNode; - SelectNode(DBTree, DBtree.GetFirst); Connection.ClearDbObjects(activeDB); - FreeAndNil(AllDatabases); - DBTree.DeleteNode(Node); - RefreshTree(False); + InvalidateVT(DBtree, VTREE_NOTLOADED_PURGECACHE, False); + ActiveDatabase := ''; except on E:Exception do MessageDlg(E.Message, mtError, [mbOK], 0); @@ -4281,11 +4250,11 @@ begin if Length(CurrentInput) = 0 then // makes only sense if the user has typed "database." begin - i := Databases.IndexOf(PrevShortToken); + i := AllDatabases.IndexOf(PrevShortToken); if i > -1 then begin // Only display tables from specified db Screen.Cursor := crHourGlass; - DBObjects := Connection.GetDBObjects(Databases[i]); + DBObjects := Connection.GetDBObjects(AllDatabases[i]); for j:=0 to DBObjects.Count-1 do addTable(DBObjects[j]); Screen.Cursor := crDefault; @@ -4294,9 +4263,9 @@ begin if Proposal.ItemList.count = 0 then begin // Add databases - for i := 0 to Databases.Count - 1 do begin - Proposal.InsertList.Add(Databases[i]); - Proposal.ItemList.Add(Format(SYNCOMPLETION_PATTERN, [ICONINDEX_DB, 'database', Databases[i]])); + for i := 0 to AllDatabases.Count - 1 do begin + Proposal.InsertList.Add(AllDatabases[i]); + Proposal.ItemList.Add(Format(SYNCOMPLETION_PATTERN, [ICONINDEX_DB, 'database', AllDatabases[i]])); end; if ActiveDatabase <> '' then begin @@ -4305,7 +4274,7 @@ begin for j:=0 to DBObjects.Count-1 do addTable(DBObjects[j]); if Length(CurrentInput) = 0 then // assume that we have already a dbname in memo - Proposal.Position := Databases.Count; + Proposal.Position := AllDatabases.Count; end; // Add functions @@ -5022,8 +4991,8 @@ begin s := DBtree.FocusedNode; if not Assigned(s) then Result := '' else case DBtree.GetNodeLevel(s) of - 2: Result := Databases[s.Parent.Index]; - 1: Result := Databases[s.Index]; + 2: Result := AllDatabases[s.Parent.Index]; + 1: Result := AllDatabases[s.Index]; else Result := ''; end; end; @@ -6130,9 +6099,9 @@ begin case Column of 0: case Sender.GetNodeLevel(Node) of 0: CellText := Connection.Parameters.Username + '@' + Connection.Parameters.Hostname; - 1: CellText := Databases[Node.Index]; + 1: CellText := AllDatabases[Node.Index]; 2: begin - DBObjects := Connection.GetDBObjects(Databases[Node.Parent.Index]); + DBObjects := Connection.GetDBObjects(AllDatabases[Node.Parent.Index]); CellText := DBObjects[Node.Index].Name; end; end; @@ -6140,8 +6109,8 @@ begin // Calculate and display the sum of all table sizes in ALL dbs if all table lists are cached lntNone: begin AllListsCached := true; - for i := 0 to Databases.Count - 1 do begin - if not Connection.DbObjectsCached(Databases[i]) then begin + for i:=0 to AllDatabases.Count-1 do begin + if not Connection.DbObjectsCached(AllDatabases[i]) then begin AllListsCached := false; break; end; @@ -6150,8 +6119,8 @@ begin Bytes := -1; if AllListsCached then begin Bytes := 0; - for i:=0 to Databases.Count-1 do begin - DBObjects := Connection.GetDBObjects(Databases[i]); + for i:=0 to AllDatabases.Count-1 do begin + DBObjects := Connection.GetDBObjects(AllDatabases[i]); Inc(Bytes, DBObjects.DataSize); end; end; @@ -6206,7 +6175,7 @@ begin Ghosted := not Connection.DbObjectsCached(db); end; 2: begin - DBObjects := Connection.GetDBObjects(Databases[Node.Parent.Index]); + DBObjects := Connection.GetDBObjects(AllDatabases[Node.Parent.Index]); // Various bug reports refer to this location where we reference a db object which is outside the range // of DBObjects. Probably a timing issue. Work around that by doing a safety check here. if Node.Index >= Cardinal(DBObjects.Count) then @@ -6220,74 +6189,36 @@ end; {** Set childcount of an expanding treenode } -procedure TMainForm.DBtreeInitChildren(Sender: TBaseVirtualTree; Node: - PVirtualNode; var ChildCount: Cardinal); +procedure TMainForm.DBtreeInitChildren(Sender: TBaseVirtualTree; Node: PVirtualNode; var ChildCount: Cardinal); var VT: TVirtualStringTree; - i, j: Integer; - DatabasesWanted: TStringList; - rx: TRegExpr; - FilterError: Boolean; begin VT := Sender as TVirtualStringTree; case VT.GetNodeLevel(Node) of // Root node has only one single child (user@host) 0: begin Screen.Cursor := crHourglass; - try - if not Assigned(AllDatabases) then begin - ShowStatusMsg( 'Reading Databases...' ); - AllDatabases := Connection.GetCol('SHOW DATABASES'); - InvalidateVT(ListDatabases, VTREE_NOTLOADED, False); + ShowStatusMsg('Reading Databases...'); + if VT.Tag = VTREE_NOTLOADED_PURGECACHE then try + AllDatabases := Connection.AllDatabases; + except + on E:Exception do begin + AllDatabases.Clear; + MessageDlg(E.Message+CRLF+CRLF+'You have no privilege to execute SHOW DATABASES. Please specify one or more databases in your session settings, if you want to see any.', mtError, [mbOK], 0); end; - if not Assigned(Databases) then - Databases := TStringList.Create; - Databases.Clear; - DatabasesWanted := Explode(';', comboOnlyDBs.Text); - FilterError := False; - if DatabasesWanted.Count > 0 then begin - // Add dbs by regular expression, avoiding duplicates - rx := TRegExpr.Create; - rx.Expression := '('+ImplodeStr('|', DatabasesWanted)+')'; - for j:=0 to AllDatabases.Count-1 do try - // The regular expression can have syntax errors which lead to an AV - if rx.Exec(AllDatabases[j]) then - Databases.Add(AllDatabases[j]); - except - FilterError := True; - break; - end; - rx.Free; - if Databases.Count = 0 then - FilterError := True; - end; - if FilterError then - comboOnlyDBs.Color := clWebPink - else - comboOnlyDBs.Color := clWindow; - FreeAndNil(DatabasesWanted); - if Databases.Count = 0 then - Databases.Assign(AllDatabases); - Databases.Sort; - - // Prioritised position of virtual system database - i := Databases.IndexOf(DBNAME_INFORMATION_SCHEMA); - if i > -1 then - Databases.Move(i, 0); - - ShowStatusMsg( IntToStr( Databases.Count ) + ' Databases', 0 ); - ChildCount := Databases.Count; - finally - ShowStatusMsg( STATUS_MSG_READY ); - Screen.Cursor := crDefault; end; + ShowStatusMsg(STATUS_MSG_READY); + VT.Tag := VTREE_LOADED; + InvalidateVT(ListDatabases, VTREE_NOTLOADED, False); + ChildCount := AllDatabases.Count; + Screen.Cursor := crDefault; end; // DB node expanding 1: begin Screen.Cursor := crHourglass; ShowStatusMsg( 'Reading objects ...' ); try - ChildCount := Connection.GetDBObjects(Databases[Node.Index]).Count; + ChildCount := Connection.GetDBObjects(AllDatabases[Node.Index]).Count; finally ShowStatusMsg( STATUS_MSG_READY ); Screen.Cursor := crDefault; @@ -6345,7 +6276,7 @@ begin tabData.TabVisible := False; end; 1: begin - newDb := Databases[Node.Index]; + newDb := AllDatabases[Node.Index]; // Selecting a database can cause an SQL error if the db was deleted from outside. Select previous node in that case. try Connection.Database := newDb; @@ -6364,7 +6295,7 @@ begin tabData.TabVisible := false; end; 2: begin - newDb := Databases[Node.Parent.Index]; + newDb := AllDatabases[Node.Parent.Index]; try Connection.Database := newDb; except on E:Exception do begin @@ -6454,7 +6385,7 @@ end; procedure TMainForm.DatabaseChanged(Database: String); begin - if (Database='') or (Databases.IndexOf(Database) > -1) then + if (Database='') or (AllDatabases.IndexOf(Database) > -1) then ActiveDatabase := Database; end; @@ -6530,11 +6461,9 @@ begin DBtree.FocusedNode := nil; // ReInit tree population - if DoResetTableCache then begin + if DoResetTableCache then Connection.ClearAllDbObjects; - FreeAndNil(AllDatabases); - end; - DBtree.ResetNode(DBTree.GetFirst); + InvalidateVT(DBtree, VTREE_NOTLOADED_PURGECACHE, True); // Reselect active or new database if present. Could have been deleted or renamed. try @@ -6590,16 +6519,13 @@ var n: PVirtualNode; begin Result := nil; - // Ensure Databases list is instantiated (by DBtree.InitChildren) - if Databases = nil then - DBtree.ReinitNode(DBtree.GetFirst, False); // TStringList.CaseSensitive= True|False is only used in .IndexOf and .Sort procs, // it does not avoid or remove duplicate items - Databases.CaseSensitive := True; - s := Databases.IndexOf(db); + AllDatabases.CaseSensitive := True; + s := AllDatabases.IndexOf(db); if s = -1 then begin - Databases.CaseSensitive := False; - s := Databases.IndexOf(db); + AllDatabases.CaseSensitive := False; + s := AllDatabases.IndexOf(db); end; if s > -1 then begin n := DBtree.GetFirstChild(DBtree.GetFirst); @@ -8403,7 +8329,6 @@ end; procedure TMainForm.actEditObjectExecute(Sender: TObject); var Obj: PDBObject; - db: String; begin debug('actEditObjectExecute()'); if ListTables.Focused then begin @@ -8418,17 +8343,8 @@ begin if CreateDatabaseForm = nil then CreateDatabaseForm := TCreateDatabaseForm.Create(Self); CreateDatabaseForm.modifyDB := ActiveDatabase; - if CreateDatabaseForm.ShowModal = mrOk then begin - db := CreateDatabaseForm.editDBName.Text; - // Add new DB to database filter if it's not empty - if comboOnlyDBs.Text <> '' then begin - comboOnlyDBs.Text := comboOnlyDBs.Text + ';' + db; - comboOnlyDBs.Items.Insert(0, comboOnlyDBs.Text); - end; - FreeAndNil(AllDatabases); - // reload db nodes and switch to new one - RefreshTree(False, db); - end; + if CreateDatabaseForm.ShowModal = mrOk then + InvalidateVT(DBtree, VTREE_NOTLOADED_PURGECACHE, True); end; 2: PlaceObjectEditor(SelectedTable); @@ -8913,79 +8829,6 @@ begin end; -procedure TMainForm.comboOnlyDBsChange(Sender: TObject); -begin - // Immediately apply database filter - RefreshTree(False); -end; - - -procedure TMainForm.comboOnlyDBsExit(Sender: TObject); -var - i, idx: Integer; - FilterText: String; -begin - // Add (move) custom filter text to (in) drop down history, if not empty - FilterText := comboOnlyDBs.Text; - idx := -1; - for i:=0 to comboOnlyDBs.Items.Count-1 do begin - if comboOnlyDBs.Items[i] = FilterText then begin - idx := i; - break; - end; - end; - if idx > -1 then - comboOnlyDBs.Items.Move(idx, 0) - else - comboOnlyDBs.Items.Insert(0, FilterText); - comboOnlyDBs.Text := FilterText; -end; - - -procedure TMainForm.comboOnlyDBsDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; - var Accept: Boolean); -begin - // DBtree dragging node over DB filter dropdown - Accept := (Source = DBtree) and (DBtree.GetNodeLevel(DBtree.FocusedNode) = 1); -end; - - -procedure TMainForm.comboOnlyDBsDragDrop(Sender, Source: TObject; X, Y: Integer); -var - dbs: TStringList; - newdb: String; -begin - // DBtree node dropped on DB filter dropdown - dbs := Explode(';', comboOnlyDBs.Text); - newdb := DBtree.Text[DBtree.FocusedNode, DBtree.FocusedColumn]; - if dbs.IndexOf(newdb) = -1 then begin - if (comboOnlyDBs.Text <> '') and (comboOnlyDBs.Text[Length(comboOnlyDBs.Text)-1] <> ';') then - comboOnlyDBs.Text := comboOnlyDBs.Text + ';'; - comboOnlyDBs.Text := comboOnlyDBs.Text + newdb; - comboOnlyDBs.Items.Insert(0, comboOnlyDBs.Text); - comboOnlyDBs.OnChange(Sender); - end; -end; - - -procedure TMainForm.comboOnlyDBsKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); -var - i: Integer; -begin - // Pressing Delete key while filters are dropped down, deletes the filter from the list - i := comboOnlyDBs.ItemIndex; - if comboOnlyDBs.DroppedDown and (Key=VK_DELETE) and (i > -1) then begin - Key := 0; - comboOnlyDBs.Items.Delete(i); - if comboOnlyDBs.Items.Count > i then - comboOnlyDBs.ItemIndex := i - else - comboOnlyDBs.ItemIndex := i-1; - comboOnlyDBs.OnChange(Sender); - end; -end; - - procedure TMainForm.actFilterPanelExecute(Sender: TObject); var MakeVisible: Boolean; diff --git a/source/mysql_connection.pas b/source/mysql_connection.pas index 762b29ac..a1ff2916 100644 --- a/source/mysql_connection.pas +++ b/source/mysql_connection.pas @@ -73,7 +73,7 @@ type TConnectionParameters = class(TObject) strict private FNetType: TNetType; - FHostname, FUsername, FPassword, FStartupScriptFilename, + FHostname, FUsername, FPassword, FAllDatabases, FStartupScriptFilename, FSSLPrivateKey, FSSLCertificate, FSSLCACertificate, FSSHHost, FSSHUser, FSSHPassword, FSSHPlinkExe, FSSHPrivateKey: String; FPort, FSSHPort, FSSHLocalPort: Integer; @@ -86,6 +86,7 @@ type property Port: Integer read FPort write FPort; property Username: String read FUsername write FUsername; property Password: String read FPassword write FPassword; + property AllDatabases: String read FAllDatabases write FAllDatabases; property StartupScriptFilename: String read FStartupScriptFilename write FStartupScriptFilename; property Options: TMySQLClientOptions read FOptions write FOptions; property SSHHost: String read FSSHHost write FSSHHost; @@ -142,6 +143,7 @@ type function GetLastError: String; function GetServerVersionStr: String; function GetServerVersionInt: Integer; + function GetAllDatabases: TStringList; function GetTableEngines: TStringList; function GetCollationTable: TMySQLQuery; function GetCollationList: TStringList; @@ -186,6 +188,7 @@ type property LastQueryDuration: Cardinal read FLastQueryDuration; property LastQueryNetworkDuration: Cardinal read FLastQueryNetworkDuration; property IsUnicode: Boolean read FIsUnicode; + property AllDatabases: TStringList read GetAllDatabases; property TableEngines: TStringList read GetTableEngines; property TableEngineDefault: String read FTableEngineDefault; property CollationTable: TMySQLQuery read GetCollationTable; @@ -673,6 +676,18 @@ begin end; +function TMySQLConnection.GetAllDatabases: TStringList; +begin + if FParameters.AllDatabases <> '' then begin + Result := TStringList.Create; + Result.Delimiter := ';'; + Result.StrictDelimiter := True; + Result.DelimitedText := FParameters.AllDatabases; + end else + Result := GetCol('SHOW DATABASES'); +end; + + {** Convert integer version to real version string } diff --git a/source/selectdbobject.pas b/source/selectdbobject.pas index 3d128043..a9b5bca2 100644 --- a/source/selectdbobject.pas +++ b/source/selectdbobject.pas @@ -106,7 +106,7 @@ procedure TfrmSelectDBObject.FormShow(Sender: TObject); begin TreeDBO.Clear; TreeDBO.RootNodeCount := Mainform.DBtree.RootNodeCount; - SetLength(FColumns, Mainform.Databases.Count); + SetLength(FColumns, Mainform.AllDatabases.Count); // TreeDBO.OnFocusChanged(TreeDBO, TreeDBO.FocusedNode, 0); editDB.Clear; editTable.Clear; @@ -186,9 +186,9 @@ begin case Sender.GetNodeLevel(Node) of 1: SetLength(FColumns[Node.Index], ChildCount); 2: begin // Table expanding - DBObjects := Mainform.Connection.GetDBObjects(Mainform.Databases[Node.Parent.Index]); + DBObjects := Mainform.Connection.GetDBObjects(Mainform.AllDatabases[Node.Parent.Index]); cols := Mainform.Connection.GetCol('SHOW COLUMNS FROM ' - + Mainform.mask(Mainform.Databases[Node.Parent.Index])+'.' + + Mainform.mask(Mainform.AllDatabases[Node.Parent.Index])+'.' + Mainform.Mask(DBObjects[Node.Index].Name)); FColumns[Node.Parent.Index][Node.Index] := cols; ChildCount := cols.Count; diff --git a/source/tabletools.pas b/source/tabletools.pas index bbb29ad9..c8b0ad89 100644 --- a/source/tabletools.pas +++ b/source/tabletools.pas @@ -285,7 +285,7 @@ begin end; comboExportOutputType.OnChange(Sender); - comboBulkTableEditDatabase.Items.Text := Mainform.Databases.Text; + comboBulkTableEditDatabase.Items.Text := Mainform.AllDatabases.Text; if comboBulkTableEditDatabase.Items.Count > 0 then comboBulkTableEditDatabase.ItemIndex := 0; @@ -504,7 +504,7 @@ begin for i:=0 to FModifiedDbs.Count-1 do Mainform.Connection.ClearDbObjects(FModifiedDbs[i]); TreeObjects.ResetNode(TreeObjects.GetFirst); - Mainform.DBtree.ResetNode(Mainform.DBtree.GetFirst); + InvalidateVT(Mainform.DBtree, VTREE_NOTLOADED_PURGECACHE, False); FModifiedDbs.Clear; end; Screen.Cursor := crDefault;