Internal refactoring: Directly bind TDBObject's to nodes in ListTables, instead of copying everything to an internal array structure first. Most events on ListTables have their own procedures now. Also, when selecting a database in the tree without expanding it and a query tab is selected, do not fetch objects. Could annoy some SQL writers which won't see the objects in selected db highlighted in that case. On the other hand this avoids loading objects in situations where you don't need them. For larger databases this should be really helpful, e.g. for the reporter of issue #1742.

This commit is contained in:
Ansgar Becker
2010-03-07 09:46:49 +00:00
parent f636bf613f
commit cc0b931551
4 changed files with 192 additions and 143 deletions

View File

@ -95,14 +95,11 @@ procedure TCopyTableForm.FormShow(Sender: TObject);
var var
i : Integer; i : Integer;
struc_data : Byte; struc_data : Byte;
NodeData: PVTreeData;
begin begin
if Mainform.DBtree.Focused then if Mainform.DBtree.Focused then
oldTableName := Mainform.SelectedTable.Name oldTableName := Mainform.SelectedTable.Name
else begin else
NodeData := Mainform.ListTables.GetNodeData(Mainform.ListTables.FocusedNode); oldTableName := Mainform.ListTables.Text[Mainform.ListTables.FocusedNode, 0];
oldTableName := NodeData.Captions[0];
end;
editNewTablename.Text := oldTableName + '_copy'; editNewTablename.Text := oldTableName + '_copy';
editNewTablename.SetFocus; editNewTablename.SetFocus;
lblNewTablename.Caption := 'Copy ''' + oldTableName + ''' to new table:'; lblNewTablename.Caption := 'Copy ''' + oldTableName + ''' to new table:';

View File

@ -876,18 +876,18 @@ object MainForm: TMainForm
TreeOptions.PaintOptions = [toHotTrack, toShowDropmark, toShowHorzGridLines, toShowVertGridLines, toThemeAware, toUseBlendedImages, toUseExplorerTheme] TreeOptions.PaintOptions = [toHotTrack, toShowDropmark, toShowHorzGridLines, toShowVertGridLines, toThemeAware, toUseBlendedImages, toUseExplorerTheme]
TreeOptions.SelectionOptions = [toFullRowSelect, toMultiSelect, toRightClickSelect] TreeOptions.SelectionOptions = [toFullRowSelect, toMultiSelect, toRightClickSelect]
OnAfterPaint = vstAfterPaint OnAfterPaint = vstAfterPaint
OnBeforePaint = ListTablesBeforePaint
OnChange = ListTablesChange OnChange = ListTablesChange
OnCompareNodes = vstCompareNodes OnCompareNodes = vstCompareNodes
OnDblClick = ListTablesDblClick OnDblClick = ListTablesDblClick
OnEditing = ListTablesEditing OnEditing = ListTablesEditing
OnFreeNode = vstFreeNode OnGetText = ListTablesGetText
OnGetText = vstGetText OnGetImageIndex = ListTablesGetImageIndex
OnGetImageIndex = vstGetImageIndex
OnGetHint = vstGetHint OnGetHint = vstGetHint
OnGetNodeDataSize = vstGetNodeDataSize OnGetNodeDataSize = ListTablesGetNodeDataSize
OnHeaderClick = vstHeaderClick OnHeaderClick = vstHeaderClick
OnHeaderDraggedOut = vstHeaderDraggedOut OnHeaderDraggedOut = vstHeaderDraggedOut
OnInitNode = vstInitNode OnInitNode = ListTablesInitNode
OnNewText = ListTablesNewText OnNewText = ListTablesNewText
Columns = < Columns = <
item item

View File

@ -550,10 +550,7 @@ type
procedure ValidateControls(Sender: TObject); procedure ValidateControls(Sender: TObject);
procedure ValidateQueryControls(Sender: TObject); procedure ValidateQueryControls(Sender: TObject);
procedure RefreshQueryHelpers; procedure RefreshQueryHelpers;
procedure LoadDatabaseProperties(db: String);
procedure ShowHost; procedure ShowHost;
procedure ShowDatabase(db: String);
procedure ShowDBProperties(db: String);
procedure DataGridBeforePaint(Sender: TBaseVirtualTree; procedure DataGridBeforePaint(Sender: TBaseVirtualTree;
TargetCanvas: TCanvas); TargetCanvas: TCanvas);
procedure LogSQL(Msg: String; Category: TMySQLLogCategory=lcInfo); procedure LogSQL(Msg: String; Category: TMySQLLogCategory=lcInfo);
@ -676,6 +673,14 @@ type
procedure ListStatusBeforePaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas); procedure ListStatusBeforePaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas);
procedure ListProcessesBeforePaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas); procedure ListProcessesBeforePaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas);
procedure ListCommandStatsBeforePaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas); procedure ListCommandStatsBeforePaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas);
procedure ListTablesBeforePaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas);
procedure ListTablesGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind;
Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer);
procedure ListTablesGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer);
procedure ListTablesGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
procedure ListTablesInitNode(Sender: TBaseVirtualTree; ParentNode,
Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
procedure vstAfterPaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas); procedure vstAfterPaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas);
procedure actCopyOrCutExecute(Sender: TObject); procedure actCopyOrCutExecute(Sender: TObject);
procedure actPasteExecute(Sender: TObject); procedure actPasteExecute(Sender: TObject);
@ -806,8 +811,7 @@ type
VTRowDataListVariables, VTRowDataListVariables,
VTRowDataListStatus, VTRowDataListStatus,
VTRowDataListProcesses, VTRowDataListProcesses,
VTRowDataListCommandStats, VTRowDataListCommandStats: TVTreeDataArray;
VTRowDataListTables: TVTreeDataArray;
// Variables set by preferences dialog // Variables set by preferences dialog
prefRememberFilters: Boolean; prefRememberFilters: Boolean;
@ -1945,6 +1949,7 @@ procedure TMainForm.actTableToolsExecute(Sender: TObject);
var var
Act: TAction; Act: TAction;
InDBTree: Boolean; InDBTree: Boolean;
Node: PVirtualNode;
begin begin
// Show table tools dialog // Show table tools dialog
if TableToolsDialog = nil then if TableToolsDialog = nil then
@ -1954,8 +1959,13 @@ begin
and (TPopupMenu((Act.ActionComponent as TMenuItem).GetParentMenu).PopupComponent = DBTree); and (TPopupMenu((Act.ActionComponent as TMenuItem).GetParentMenu).PopupComponent = DBTree);
if InDBTree then if InDBTree then
TableToolsDialog.SelectedTables.Text := SelectedTable.Name TableToolsDialog.SelectedTables.Text := SelectedTable.Name
else else begin
TableToolsDialog.SelectedTables := GetVTCaptions(ListTables, True); Node := ListTables.GetFirstSelected;
while Assigned(Node) do begin
TableToolsDialog.SelectedTables.Add(ListTables.Text[Node, 0]);
Node := ListTables.GetNextSelected(Node);
end;
end;
if Sender = actMaintenance then if Sender = actMaintenance then
TableToolsDialog.ToolMode := tmMaintenance TableToolsDialog.ToolMode := tmMaintenance
else if Sender = actFindTextOnServer then else if Sender = actFindTextOnServer then
@ -2318,11 +2328,12 @@ end;
procedure TMainForm.actDropObjectsExecute(Sender: TObject); procedure TMainForm.actDropObjectsExecute(Sender: TObject);
var var
AllCount : Integer; AllCount : Integer;
Tables, Views, Functions, Procedures, Triggers: TStringList; Tables, Views, Functions, Procedures, Triggers, List: TStringList;
msg, activeDB : String; msg, activeDB : String;
InDBTree: Boolean; InDBTree: Boolean;
Act: TAction; Act: TAction;
Node: PVirtualNode; Node: PVirtualNode;
Obj: PDBObject;
procedure DoDrop(Kind: String; List: TStringList; MultiDrops: Boolean); procedure DoDrop(Kind: String; List: TStringList; MultiDrops: Boolean);
var var
@ -2389,11 +2400,19 @@ begin
end; end;
end else begin end else begin
// Invoked from database tab // Invoked from database tab
Tables := GetVTCaptions(ListTables, True, 0, [lntTable]); Node := ListTables.GetFirstSelected;
Views := GetVTCaptions(ListTables, True, 0, [lntView]); while Assigned(Node) do begin
Procedures := GetVTCaptions(ListTables, True, 0, [lntProcedure]); Obj := ListTables.GetNodeData(Node);
Functions := GetVTCaptions(ListTables, True, 0, [lntFunction]); case Obj.NodeType of
Triggers := GetVTCaptions(ListTables, True, 0, [lntTrigger]); lntView: List := Views;
lntProcedure: List := Procedures;
lntFunction: List := Functions;
lntTrigger: List := Triggers;
else List := Tables;
end;
List.Add(Obj.Name);
Node := ListTables.GetNextSelected(Node);
end;
end; end;
// Fix actions temporarily enabled for popup menu. // Fix actions temporarily enabled for popup menu.
@ -2492,6 +2511,7 @@ begin
ConnectionAttempt := TMySQLConnection.Create(Self); ConnectionAttempt := TMySQLConnection.Create(Self);
ConnectionAttempt.OnLog := LogSQL; ConnectionAttempt.OnLog := LogSQL;
ConnectionAttempt.OnDatabaseChanged := DatabaseChanged; ConnectionAttempt.OnDatabaseChanged := DatabaseChanged;
ConnectionAttempt.ObjectNamesInSelectedDB := SynSQLSyn1.TableNames;
ConnectionAttempt.Parameters := Params; ConnectionAttempt.Parameters := Params;
try try
ConnectionAttempt.Active := True; ConnectionAttempt.Active := True;
@ -2732,8 +2752,8 @@ begin
List.Tag := VTREE_NOTLOADED; List.Tag := VTREE_NOTLOADED;
List.Repaint; List.Repaint;
end else if tab1 = tabDatabase then begin end else if tab1 = tabDatabase then begin
RefreshTreeDB(ActiveDatabase); ListTables.Tag := VTREE_NOTLOADED_PURGECACHE;
LoadDatabaseProperties(ActiveDatabase); ListTables.Invalidate;
end else if tab1 = tabData then begin end else if tab1 = tabData then begin
DataGrid.Tag := VTREE_NOTLOADED_PURGECACHE; DataGrid.Tag := VTREE_NOTLOADED_PURGECACHE;
DataGrid.Invalidate; DataGrid.Invalidate;
@ -3315,21 +3335,6 @@ begin
end; end;
procedure TMainForm.ShowDatabase(db: String);
begin
if (not DBtree.Dragging) and (
(PageControlMain.ActivePage = tabHost) or
(PageControlMain.ActivePage = tabData)
) then PageControlMain.ActivePage := tabDatabase;
tabDatabase.TabVisible := true;
tabEditor.TabVisible := false;
tabData.TabVisible := false;
ShowDBProperties( db );
end;
procedure TMainForm.actDataShowNextExecute(Sender: TObject); procedure TMainForm.actDataShowNextExecute(Sender: TObject);
begin begin
// Show next X rows in datagrid // Show next X rows in datagrid
@ -3677,83 +3682,38 @@ begin
end; end;
procedure TMainForm.LoadDatabaseProperties(db: String); procedure TMainForm.ListTablesBeforePaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas);
var var
i, img, NumObj: Integer; i, NumObj: Integer;
Obj: TDBObject; Obj: TDBObject;
Objects: TDBObjectList; Objects: TDBObjectList;
Cap, SelectedCaptions, NumObjects: TStringList; NumObjects: TStringList;
Msg: String; Msg: String;
vt: TVirtualStringTree;
begin begin
// DB-Properties // DB-Properties
vt := Sender as TVirtualStringTree;
if vt.Tag = VTREE_LOADED then
Exit;
Screen.Cursor := crHourGlass; Screen.Cursor := crHourGlass;
// Remember selected nodes ShowStatus( 'Displaying objects from "' + ActiveDatabase + '" ...' );
SelectedCaptions := GetVTCaptions(ListTables, True); Objects := Connection.GetDBObjects(ActiveDatabase, vt.Tag = VTREE_NOTLOADED_PURGECACHE);
Objects := Connection.GetDBObjects(db);
NumObjects := TStringList.Create;
ShowStatus( 'Displaying objects from "' + db + '" ...' );
ListTables.BeginUpdate; ListTables.BeginUpdate;
ListTables.Clear; ListTables.RootNodeCount := Objects.Count;
ListTables.ReinitChildren(nil, false);
ListTables.EndUpdate;
vt.Tag := VTREE_LOADED;
SetLength(VTRowDataListTables, Objects.Count); NumObjects := TStringList.Create;
for i:=0 to Objects.Count-1 do begin for i:=0 to Objects.Count-1 do begin
Obj := Objects[i]; Obj := Objects[i];
VTRowDataListTables[i].Captions := TStringList.Create;
Cap := VTRowDataListTables[i].Captions;
// Object name
Cap.Add(Obj.Name);
if Obj.Rows > -1 then Cap.Add(FormatNumber(Obj.Rows))
else Cap.Add('');
if Obj.Size > -1 then Cap.Add(FormatByteNumber(Obj.Size))
else Cap.Add('');
VTRowDataListTables[i].NodeType := Obj.NodeType;
// Find icon
case Obj.NodeType of
lntTable: img := ICONINDEX_TABLE;
lntView: img := ICONINDEX_VIEW;
lntProcedure: img := ICONINDEX_STOREDPROCEDURE;
lntFunction: img := ICONINDEX_STOREDFUNCTION;
lntTrigger: img := ICONINDEX_TRIGGER;
else img := -1;
end;
NumObj := StrToIntDef(NumObjects.Values[Obj.ObjType], 0); NumObj := StrToIntDef(NumObjects.Values[Obj.ObjType], 0);
Inc(NumObj); Inc(NumObj);
NumObjects.Values[Obj.ObjType] := IntToStr(NumObj); NumObjects.Values[Obj.ObjType] := IntToStr(NumObj);
VTRowDataListTables[i].ImageIndex := img;
if Obj.Created = 0 then Cap.Add('')
else Cap.Add(DateTimeToStr(Obj.Created));
if Obj.Updated = 0 then Cap.Add('')
else Cap.Add(DateTimeToStr(Obj.Updated));
Cap.Add(Obj.Engine);
Cap.Add(Obj.Comment);
if Obj.Version > -1 then Cap.Add(IntToStr(Obj.Version))
else Cap.Add('');
Cap.Add(Obj.RowFormat);
if Obj.AvgRowLen > -1 then Cap.Add(FormatByteNumber(Obj.AvgRowLen))
else Cap.Add('');
if Obj.MaxDataLen > -1 then Cap.Add(FormatByteNumber(Obj.MaxDataLen))
else Cap.Add('');
if Obj.IndexLen > -1 then Cap.Add(FormatByteNumber(Obj.IndexLen))
else Cap.Add('');
if Obj.DataFree > -1 then Cap.Add(FormatByteNumber(Obj.DataFree))
else Cap.Add('');
if Obj.AutoInc > -1 then Cap.Add(FormatNumber(Obj.AutoInc))
else Cap.Add('');
if Obj.LastChecked = 0 then Cap.Add('')
else Cap.Add(DateTimeToStr(Obj.LastChecked));
Cap.Add(Obj.Collation);
if Obj.Checksum > -1 then Cap.Add(IntToStr(Obj.Checksum))
else Cap.Add('');
Cap.Add(Obj.CreateOptions);
Cap.Add(Obj.ObjType);
end; end;
ListTables.RootNodeCount := Length(VTRowDataListTables); Msg := ActiveDatabase + ': ' + FormatNumber(Objects.Count) + ' ';
ListTables.EndUpdate;
SetVTSelection(ListTables, SelectedCaptions);
Msg := db + ': ' + FormatNumber(Objects.Count) + ' ';
if NumObjects.Count = 1 then if NumObjects.Count = 1 then
Msg := Msg + LowerCase(NumObjects.Names[0]) Msg := Msg + LowerCase(NumObjects.Names[0])
else else
@ -3772,23 +3732,84 @@ begin
Delete(Msg, Length(Msg)-1, 2); Delete(Msg, Length(Msg)-1, 2);
Msg := Msg + ')'; Msg := Msg + ')';
end; end;
showstatus(Msg, 0); ShowStatus(Msg, 0);
tabDatabase.Caption := sstr('Database: ' + db, 30);
ShowStatus(STATUS_MSG_READY); ShowStatus(STATUS_MSG_READY);
Screen.Cursor := crDefault; Screen.Cursor := crDefault;
// Ensure tree db node displays its chidren initialized // Ensure tree db node displays its chidren initialized
DBtree.ReinitChildren(FindDBNode(db), False); DBtree.ReinitChildren(FindDBNode(ActiveDatabase), False);
ValidateControls(Self); ValidateControls(Self);
end; end;
{ Show tables and their properties on the tabsheet "Database" } procedure TMainForm.ListTablesGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode;
procedure TMainForm.ShowDBProperties(db: String); Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer);
var
Obj: PDBObject;
begin begin
Screen.Cursor := crHourglass; if not (Kind in [ikNormal, ikSelected]) then
PageControlMainChange(Self); Exit;
ShowStatus( STATUS_MSG_READY ); if Column <> (Sender as TVirtualStringTree).Header.MainColumn then
Screen.Cursor := crDefault; Exit;
Obj := Sender.GetNodeData(Node);
case Obj.NodeType of
lntTable: ImageIndex := ICONINDEX_TABLE;
lntView: ImageIndex := ICONINDEX_VIEW;
lntProcedure: ImageIndex := ICONINDEX_STOREDPROCEDURE;
lntFunction: ImageIndex := ICONINDEX_STOREDFUNCTION;
lntTrigger: ImageIndex := ICONINDEX_TRIGGER;
else ImageIndex := -1;
end;
end;
procedure TMainForm.ListTablesGetNodeDataSize(Sender: TBaseVirtualTree;
var NodeDataSize: Integer);
begin
NodeDataSize := SizeOf(TDBObject);
end;
procedure TMainForm.ListTablesGetText(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
var CellText: string);
var
Obj: PDBObject;
begin
Obj := Sender.GetNodeData(Node);
CellText := '';
case Column of
0: CellText := Obj.Name;
1: if Obj.Rows > -1 then CellText := FormatNumber(Obj.Rows);
2: if Obj.Size > -1 then CellText := FormatByteNumber(Obj.Size);
3: if Obj.Created <> 0 then CellText := DateTimeToStr(Obj.Created);
4: if Obj.Updated <> 0 then CellText := DateTimeToStr(Obj.Updated);
5: CellText := Obj.Engine;
6: CellText := Obj.Comment;
7: if Obj.Version > -1 then CellText := IntToStr(Obj.Version);
8: CellText := Obj.RowFormat;
9: if Obj.AvgRowLen > -1 then CellText := FormatByteNumber(Obj.AvgRowLen);
10: if Obj.MaxDataLen > -1 then CellText := FormatByteNumber(Obj.MaxDataLen);
11: if Obj.IndexLen > -1 then CellText := FormatByteNumber(Obj.IndexLen);
12: if Obj.DataFree > -1 then CellText := FormatByteNumber(Obj.DataFree);
13: if Obj.AutoInc > -1 then CellText := FormatNumber(Obj.AutoInc);
14: if Obj.LastChecked <> 0 then CellText := DateTimeToStr(Obj.LastChecked);
15: CellText := Obj.Collation;
16: if Obj.Checksum > -1 then CellText := IntToStr(Obj.Checksum);
17: CellText := Obj.CreateOptions;
18: CellText := Obj.ObjType;
end;
end;
procedure TMainForm.ListTablesInitNode(Sender: TBaseVirtualTree; ParentNode,
Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
var
Obj: PDBObject;
Objects: TDBObjectList;
begin
Obj := Sender.GetNodeData(Node);
Objects := Connection.GetDBObjects(ActiveDatabase);
Obj^ := Objects[Node.Index];
end; end;
@ -4343,11 +4364,11 @@ end;
procedure TMainForm.ListTablesEditing(Sender: TBaseVirtualTree; procedure TMainForm.ListTablesEditing(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex; var Allowed: Boolean); Node: PVirtualNode; Column: TColumnIndex; var Allowed: Boolean);
var var
NodeData: PVTreeData; Obj: PDBObject;
begin begin
// Tables and views can be renamed, routines cannot // Tables and views can be renamed, routines cannot
NodeData := Sender.GetNodeData(Node); Obj := Sender.GetNodeData(Node);
Allowed := NodeData.NodeType in [lntTable, lntView]; Allowed := Obj.NodeType in [lntTable, lntView];
end; end;
@ -4357,22 +4378,22 @@ end;
procedure TMainForm.ListTablesNewText(Sender: TBaseVirtualTree; Node: procedure TMainForm.ListTablesNewText(Sender: TBaseVirtualTree; Node:
PVirtualNode; Column: TColumnIndex; NewText: String); PVirtualNode; Column: TColumnIndex; NewText: String);
var var
NodeData : PVTreeData; Obj: PDBObject;
begin begin
// Fetch data from node // Fetch data from node
NodeData := Sender.GetNodeData(Node); Obj := Sender.GetNodeData(Node);
// Try to rename, on any error abort and don't rename ListItem // Try to rename, on any error abort and don't rename ListItem
try try
ensureValidIdentifier( NewText ); ensureValidIdentifier( NewText );
// rename table // rename table
Connection.Query('RENAME TABLE ' + mask(NodeData.Captions[0]) + ' TO ' + mask(NewText)); Connection.Query('RENAME TABLE ' + mask(Obj.Name) + ' TO ' + mask(NewText));
if SynSQLSyn1.TableNames.IndexOf( NewText ) = -1 then begin if SynSQLSyn1.TableNames.IndexOf( NewText ) = -1 then begin
SynSQLSyn1.TableNames.Add(NewText); SynSQLSyn1.TableNames.Add(NewText);
end; end;
// Update nodedata // Update nodedata
NodeData.Captions[0] := NewText; Obj.Name := NewText;
// Now the active tree db has to be updated. But calling RefreshTreeDB here causes an AV // Now the active tree db has to be updated. But calling RefreshTreeDB here causes an AV
// so we do it manually here // so we do it manually here
Connection.ClearDbObjects(ActiveDatabase); Connection.ClearDbObjects(ActiveDatabase);
@ -4754,7 +4775,7 @@ procedure TMainForm.popupDBPopup(Sender: TObject);
var var
L: Cardinal; L: Cardinal;
HasFocus, InDBTree: Boolean; HasFocus, InDBTree: Boolean;
NodeData: PVTreeData; Obj: PDBObject;
begin begin
// DBtree and ListTables both use popupDB as menu. Find out which of them was rightclicked. // DBtree and ListTables both use popupDB as menu. Find out which of them was rightclicked.
if Sender is TPopupMenu then if Sender is TPopupMenu then
@ -4793,8 +4814,8 @@ begin
actDropObjects.Enabled := ListTables.SelectedCount > 0; actDropObjects.Enabled := ListTables.SelectedCount > 0;
actEmptyTables.Enabled := False; actEmptyTables.Enabled := False;
if HasFocus then begin if HasFocus then begin
NodeData := ListTables.GetNodeData(ListTables.FocusedNode); Obj := ListTables.GetNodeData(ListTables.FocusedNode);
actEmptyTables.Enabled := NodeData.NodeType in [lntTable, lntView]; actEmptyTables.Enabled := Obj.NodeType in [lntTable, lntView];
end; end;
actEditObject.Enabled := HasFocus; actEditObject.Enabled := HasFocus;
// Show certain items which are valid only here // Show certain items which are valid only here
@ -5101,9 +5122,6 @@ end;
procedure TMainForm.SetSelectedDatabase(db: String); procedure TMainForm.SetSelectedDatabase(db: String);
var var
n, f: PVirtualNode; n, f: PVirtualNode;
i: Integer;
DBObjects: TDBObjectList;
Tables: String;
begin begin
if db = '' then if db = '' then
n := DBtree.GetFirst n := DBtree.GetFirst
@ -5114,11 +5132,6 @@ begin
f := DBtree.FocusedNode; f := DBtree.FocusedNode;
if (not Assigned(f)) or (f.Parent <> n) then if (not Assigned(f)) or (f.Parent <> n) then
SelectNode(DBtree, n); SelectNode(DBtree, n);
// Add object names to highlighter
DBObjects := Connection.GetDBObjects(db);
for i:=0 to DBObjects.Count-1 do
Tables := Tables + DBObjects[i].Name + CRLF;
SynSQLSyn1.TableNames.Text := Trim(Tables);
end else end else
raise Exception.Create('Database node ' + db + ' not found in tree.'); raise Exception.Create('Database node ' + db + ' not found in tree.');
end; end;
@ -5607,8 +5620,6 @@ begin
Result := @VTRowDataListCommandStats Result := @VTRowDataListCommandStats
else if VT = ListProcesses then else if VT = ListProcesses then
Result := @VTRowDataListProcesses Result := @VTRowDataListProcesses
else if VT = ListTables then
Result := @VTRowDataListTables
else begin else begin
raise Exception.Create( VT.ClassName + ' "' + VT.Name + '" doesn''t have an assigned array with data.' ); raise Exception.Create( VT.ClassName + ' "' + VT.Name + '" doesn''t have an assigned array with data.' );
end; end;
@ -5624,7 +5635,6 @@ begin
if P = @VTRowDataListStatus then Exit; if P = @VTRowDataListStatus then Exit;
if P = @VTRowDataListCommandStats then Exit; if P = @VTRowDataListCommandStats then Exit;
if P = @VTRowDataListProcesses then Exit; if P = @VTRowDataListProcesses then Exit;
if P = @VTRowDataListTables then Exit;
raise Exception.Create('Assertion failed: Invalid global VT array.'); raise Exception.Create('Assertion failed: Invalid global VT array.');
end; end;
@ -6332,7 +6342,7 @@ end;
procedure TMainForm.DBtreeFocusChanged(Sender: TBaseVirtualTree; procedure TMainForm.DBtreeFocusChanged(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex); Node: PVirtualNode; Column: TColumnIndex);
var var
newDb, newDbObject: String; newDb, oldDb, newDbObject: String;
begin begin
debug('DBtreeFocusChanged()'); debug('DBtreeFocusChanged()');
SelectedTableCreateStatement := ''; SelectedTableCreateStatement := '';
@ -6354,7 +6364,12 @@ begin
Exit; Exit;
end; end;
end; end;
ShowDatabase(newDb); if (not DBtree.Dragging)
and ((PageControlMain.ActivePage = tabHost) or(PageControlMain.ActivePage = tabData)) then
PageControlMain.ActivePage := tabDatabase;
tabDatabase.TabVisible := true;
tabEditor.TabVisible := false;
tabData.TabVisible := false;
end; end;
2: begin 2: begin
newDb := Databases[Node.Parent.Index]; newDb := Databases[Node.Parent.Index];
@ -6385,9 +6400,19 @@ begin
end; end;
end; end;
end; end;
if Assigned(PreviousFocusedNode) then case DBTree.GetNodeLevel(PreviousFocusedNode) of
0: oldDb := '';
1: oldDb := DBTree.Text[PreviousFocusedNode, 0];
2: oldDb := DBTree.Text[PreviousFocusedNode.Parent, 0];
end;
if newDb <> oldDb then begin
tabDatabase.Caption := sstr('Database: ' + newDb, 30);
ListTables.ClearSelection;
ListTables.FocusedNode := nil;
ListTables.Tag := VTREE_NOTLOADED;
ListTables.Invalidate;
end;
PreviousFocusedNode := DBTree.FocusedNode; PreviousFocusedNode := DBTree.FocusedNode;
if newDb <> '' then
LoadDatabaseProperties(newDb);
FixQueryTabCloseButtons; FixQueryTabCloseButtons;
SetWindowCaption; SetWindowCaption;
end; end;
@ -8183,15 +8208,15 @@ end;
procedure TMainForm.actEditObjectExecute(Sender: TObject); procedure TMainForm.actEditObjectExecute(Sender: TObject);
var var
NodeData: PVTreeData; Obj: PDBObject;
db: String; db: String;
begin begin
debug('actEditObjectExecute()'); debug('actEditObjectExecute()');
if ListTables.Focused then begin if ListTables.Focused then begin
// Got here from ListTables.OnDblClick or ListTables's context menu item "Edit" // Got here from ListTables.OnDblClick or ListTables's context menu item "Edit"
NodeData := ListTables.GetNodeData(ListTables.FocusedNode); Obj := ListTables.GetNodeData(ListTables.FocusedNode);
if (NodeData.Captions[0] <> SelectedTable.Name) or (NodeData.NodeType <> SelectedTable.NodeType) then if (Obj.Name <> SelectedTable.Name) or (Obj.NodeType <> SelectedTable.NodeType) then
SelectDBObject(NodeData.Captions[0], NodeData.NodeType); SelectDBObject(Obj.Name, Obj.NodeType);
end; end;
case GetFocusedTreeNodeType of case GetFocusedTreeNodeType of
@ -8238,13 +8263,15 @@ end;
procedure TMainForm.ListTablesDblClick(Sender: TObject); procedure TMainForm.ListTablesDblClick(Sender: TObject);
var var
NodeData: PVTreeData; Obj: PDBObject;
vt: TVirtualStringTree;
begin begin
// DoubleClick: Display editor // DoubleClick: Display editor
debug('ListTablesDblClick()'); debug('ListTablesDblClick()');
if Assigned(ListTables.FocusedNode) then begin vt := Sender as TVirtualStringTree;
NodeData := ListTables.GetNodeData(ListTables.FocusedNode); if Assigned(vt.FocusedNode) then begin
SelectDBObject(ListTables.Text[ListTables.FocusedNode, ListTables.FocusedColumn], NodeData.NodeType); Obj := vt.GetNodeData(vt.FocusedNode);
SelectDBObject(vt.Text[vt.FocusedNode, vt.FocusedColumn], Obj.NodeType);
PageControlMainChange(Sender); PageControlMainChange(Sender);
end; end;
end; end;

View File

@ -16,6 +16,7 @@ type
Rows, Size, Version, AvgRowLen, MaxDataLen, IndexLen, DataLen, DataFree, AutoInc, CheckSum: Int64; Rows, Size, Version, AvgRowLen, MaxDataLen, IndexLen, DataLen, DataFree, AutoInc, CheckSum: Int64;
NodeType: TListNodeType; NodeType: TListNodeType;
end; end;
PDBObject = ^TDBObject;
TDBObjectList = TObjectList<TDBObject>; TDBObjectList = TObjectList<TDBObject>;
{$M+} // Needed to add published properties {$M+} // Needed to add published properties
@ -96,6 +97,7 @@ type
FCharsetTable: TMySQLQuery; FCharsetTable: TMySQLQuery;
FInformationSchemaObjects: TStringList; FInformationSchemaObjects: TStringList;
FDBObjectLists: TStringList; FDBObjectLists: TStringList;
FObjectNamesInSelectedDB: TStrings;
procedure SetActive(Value: Boolean); procedure SetActive(Value: Boolean);
procedure SetDatabase(Value: String); procedure SetDatabase(Value: String);
function GetThreadId: Cardinal; function GetThreadId: Cardinal;
@ -115,6 +117,7 @@ type
function ParseDateTime(Str: String): TDateTime; function ParseDateTime(Str: String): TDateTime;
procedure Log(Category: TMySQLLogCategory; Msg: String); procedure Log(Category: TMySQLLogCategory; Msg: String);
procedure ClearCache; procedure ClearCache;
procedure SetObjectNamesInSelectedDB;
public public
constructor Create(AOwner: TComponent); override; constructor Create(AOwner: TComponent); override;
destructor Destroy; override; destructor Destroy; override;
@ -153,6 +156,7 @@ type
property CharsetTable: TMySQLQuery read GetCharsetTable; property CharsetTable: TMySQLQuery read GetCharsetTable;
property CharsetList: TStringList read GetCharsetList; property CharsetList: TStringList read GetCharsetList;
property InformationSchemaObjects: TStringList read GetInformationSchemaObjects; property InformationSchemaObjects: TStringList read GetInformationSchemaObjects;
property ObjectNamesInSelectedDB: TStrings read FObjectNamesInSelectedDB write FObjectNamesInSelectedDB;
published published
property Active: Boolean read FActive write SetActive default False; property Active: Boolean read FActive write SetActive default False;
property Database: String read FDatabase write SetDatabase; property Database: String read FDatabase write SetDatabase;
@ -452,6 +456,7 @@ begin
FOnDatabaseChanged(Value); FOnDatabaseChanged(Value);
end else end else
Query('USE '+QuoteIdent(Value), False); Query('USE '+QuoteIdent(Value), False);
SetObjectNamesInSelectedDB;
end; end;
end; end;
@ -1122,6 +1127,26 @@ begin
if not Assigned(FDBObjectLists) then if not Assigned(FDBObjectLists) then
FDBObjectLists := TStringList.Create; FDBObjectLists := TStringList.Create;
FDBObjectLists.AddObject(db, Result); FDBObjectLists.AddObject(db, Result);
SetObjectNamesInSelectedDB;
end;
end;
procedure TMySQLConnection.SetObjectNamesInSelectedDB;
var
i: Integer;
Objects: TDBObjectList;
ObjNames: String;
begin
// Add object names to additional stringlist
if Assigned(FObjectNamesInSelectedDB) and DbObjectsCached(FDatabase) then begin
Objects := GetDbObjects(FDatabase);
for i:=0 to Objects.Count-1 do
ObjNames := ObjNames + Objects[i].Name + CRLF;
if FObjectNamesInSelectedDB.Text <> ObjNames then
FObjectNamesInSelectedDB.Text := ObjNames;
end; end;
end; end;