Move database filter again from mainform to session manager, so people without privilege to run SHOW DATABASE are not stuck. Fixes issue #1485. Also, allow to see available databases when user does a dropdown. Also, simplify logic for refreshing database list in mainform.

This commit is contained in:
Ansgar Becker
2010-04-22 15:16:27 +00:00
parent 9b786c81e0
commit 97f01a175b
13 changed files with 205 additions and 309 deletions

View File

@ -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

View File

@ -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)

View File

@ -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';

View File

@ -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;

View File

@ -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;

View File

@ -3513,10 +3513,16 @@ begin
if not Assigned(VT) then
Exit;
VT.Tag := RefreshTag;
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);

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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<TQueryTab>;
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);
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]);
ShowStatusMsg('Reading Databases...');
if VT.Tag = VTREE_NOTLOADED_PURGECACHE then try
AllDatabases := Connection.AllDatabases;
except
FilterError := True;
break;
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;
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 );
ShowStatusMsg(STATUS_MSG_READY);
VT.Tag := VTREE_LOADED;
InvalidateVT(ListDatabases, VTREE_NOTLOADED, False);
ChildCount := AllDatabases.Count;
Screen.Cursor := crDefault;
end;
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;

View File

@ -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
}

View File

@ -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;

View File

@ -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;