Integrate stored procedures and functions into the GUI flow, so they are visible like tables and editable from everywhere.

- FetchDbTableList now makes use of various tables in INFORMATION_SCHEMA if available - the only way of listing stored routines.
- If a routine is selected, Table + Data tab hide their grids and display a corresponding message instead. Seemed the only way to keep the normal flow of clicks, not changing too much click logic.
This commit is contained in:
Ansgar Becker
2009-03-02 21:40:44 +00:00
parent 36c8937abb
commit dbb84e6df9
9 changed files with 419 additions and 231 deletions

View File

@ -282,11 +282,13 @@ const
// Node types of Virtual Tree nodes // Node types of Virtual Tree nodes
NODETYPE_DEFAULT = 0; NODETYPE_DEFAULT = 0;
NODETYPE_TABLE = 1; NODETYPE_DB = 1;
NODETYPE_VIEW = 2; NODETYPE_TABLE = 2;
NODETYPE_DB = 3; NODETYPE_CRASHED_TABLE = 3;
NODETYPE_COLUMN = 4; NODETYPE_VIEW = 4;
NODETYPE_CRASHED_TABLE = 5; NODETYPE_FUNCTION = 5;
NODETYPE_PROCEDURE = 6;
NODETYPE_COLUMN = 7;
// Data grid: How many bytes to fetch from data fields that are potentially large. // Data grid: How many bytes to fetch from data fields that are potentially large.
GRIDMAXDATA: Integer = 256; GRIDMAXDATA: Integer = 256;
@ -306,3 +308,24 @@ const
MSG_COPYMAXSIZE = 'Copying data is limited to %s but more data is available. ' MSG_COPYMAXSIZE = 'Copying data is limited to %s but more data is available. '
+ 'Only %s out of %s rows were copied.' + CRLF + CRLF + 'Only %s out of %s rows were copied.' + CRLF + CRLF
+ 'Increase the value in Tools > Preferences > Export if you need more.'; + 'Increase the value in Tools > Preferences > Export if you need more.';
DBO_NAME = 'Name';
DBO_TYPE = 'Type';
DBO_ENGINE = 'Engine';
DBO_VERSION = 'Version';
DBO_ROWFORMAT = 'Row_format';
DBO_ROWS = 'Rows';
DBO_AVGROWLEN = 'Avg_row_length';
DBO_DATALEN = 'Data_length';
DBO_MAXDATALEN = 'Max_data_length';
DBO_INDEXLEN = 'Index_length';
DBO_DATAFREE = 'Data_free';
DBO_AUTOINC = 'Auto_increment';
DBO_CREATED = 'Create_time';
DBO_UPDATED = 'Update_time';
DBO_CHECKED = 'Check_time';
DBO_COLLATION = 'Collation';
DBO_CHECKSUM = 'Checksum';
DBO_CROPTIONS = 'Create_options';
DBO_COMMENT = 'Comment';

View File

@ -167,7 +167,7 @@ begin
else if Mainform.ActiveDatabase <> '' then begin else if Mainform.ActiveDatabase <> '' then begin
ds := Mainform.FetchDbTableList(Mainform.ActiveDatabase); ds := Mainform.FetchDbTableList(Mainform.ActiveDatabase);
while not ds.Eof do begin while not ds.Eof do begin
SelectedTables.Add(ds.Fields[0].AsWideString); SelectedTables.Add(ds.FieldByName(DBO_NAME).AsWideString);
ds.Next; ds.Next;
end; end;
end; end;
@ -361,17 +361,17 @@ end;
procedure TExportSQLForm.comboSelectDatabaseChange(Sender: TObject); procedure TExportSQLForm.comboSelectDatabaseChange(Sender: TObject);
var var
i : Integer; i : Integer;
sql: WideString;
CheckThisItem: Boolean; CheckThisItem: Boolean;
ds: TDataset;
begin begin
// read tables from db // read tables from db
checkListTables.Items.Clear; checkListTables.Items.Clear;
ds := Mainform.FetchDbTableList(comboSelectDatabase.Text);
// Fetch tables from DB while not ds.Eof do begin
sql := 'FROM ' + MainForm.mask(comboSelectDatabase.Text); if GetDBObjectType(ds.Fields) = NODETYPE_TABLE then
if Mainform.mysql_version > 50002 then sql := 'SHOW FULL TABLES ' + sql + ' WHERE table_type=''BASE TABLE''' checkListTables.Items.Add(ds.FieldByName(DBO_NAME).AsWideString);
else sql := 'SHOW TABLES ' + sql; ds.Next;
checkListTables.Items.Text := Mainform.GetCol( sql ).Text; end;
// select all/some: // select all/some:
for i:=0 to checkListTables.Items.Count-1 do for i:=0 to checkListTables.Items.Count-1 do

View File

@ -2327,6 +2327,8 @@ end;
// Tell type of db object (table|view) by a given row from a SHOW TABLE STATUS result // Tell type of db object (table|view) by a given row from a SHOW TABLE STATUS result
function GetDBObjectType( TableStatus: TFields ): Byte; function GetDBObjectType( TableStatus: TFields ): Byte;
var
t: String;
begin begin
{** {**
@see http://dev.mysql.com/doc/refman/5.1/en/show-table-status.html @see http://dev.mysql.com/doc/refman/5.1/en/show-table-status.html
@ -2337,21 +2339,28 @@ begin
"Views bla references invalid..." "Views bla references invalid..."
} }
Result := NODETYPE_TABLE; Result := NODETYPE_TABLE;
if (TableStatus.Count>=3) then begin if TableStatus.FindField('Type') <> nil then begin
// Result from SHOW TABLE STATUS t := TableStatus.FindField('Type').AsString;
if t = 'BASE TABLE' then
Result := NODETYPE_TABLE
else if t = 'VIEW' then
Result := NODETYPE_VIEW
else if t = 'FUNCTION' then
Result := NODETYPE_FUNCTION
else if t = 'PROCEDURE' then
Result := NODETYPE_PROCEDURE;
end else begin
if if
TableStatus[1].IsNull and // Engine column is NULL for views TableStatus[1].IsNull and // Engine column is NULL for views
TableStatus[2].IsNull and TableStatus[2].IsNull and
(Pos('VIEW', UpperCase(TableStatus.FieldByName('Comment').AsWideString)) > 0) (Pos('VIEW', UpperCase(TableStatus.FieldByName(DBO_COMMENT).AsWideString)) > 0)
then Result := NODETYPE_VIEW; then Result := NODETYPE_VIEW;
if if
TableStatus[1].IsNull and TableStatus[1].IsNull and
TableStatus[2].IsNull and TableStatus[2].IsNull and
(Pos('MARKED AS CRASHED', UpperCase(TableStatus.FieldByName('Comment').AsWideString)) > 0) (Pos('MARKED AS CRASHED', UpperCase(TableStatus.FieldByName(DBO_COMMENT).AsWideString)) > 0)
then Result := NODETYPE_CRASHED_TABLE; then Result := NODETYPE_CRASHED_TABLE;
end else if (TableStatus.Count=2) // Result from SHOW FULL TABLES end;
and (UpperCase(TableStatus[1].AsWideString) = 'VIEW') then
Result := NODETYPE_VIEW;
end; end;

View File

@ -111,7 +111,8 @@ begin
ComboBoxTables.Items.Clear; ComboBoxTables.Items.Clear;
ds := Mainform.FetchDbTableList(ComboBoxDBs.Text); ds := Mainform.FetchDbTableList(ComboBoxDBs.Text);
while not ds.Eof do begin while not ds.Eof do begin
ComboBoxTables.Items.Add(ds.Fields[0].AsString); if GetDBObjectType(ds.Fields) in [NODETYPE_TABLE, NODETYPE_VIEW] then
ComboBoxTables.Items.Add(ds.FieldByName(DBO_NAME).AsString);
ds.Next; ds.Next;
end; end;
if ComboBoxTables.Items.Count > 0 then if ComboBoxTables.Items.Count > 0 then

View File

@ -149,7 +149,8 @@ begin
seltable := Mainform.SelectedTable; seltable := Mainform.SelectedTable;
ds := Mainform.FetchDbTableList(comboDatabase.Text); ds := Mainform.FetchDbTableList(comboDatabase.Text);
while not ds.Eof do begin while not ds.Eof do begin
comboTable.Items.Add(ds.Fields[0].AsWideString); if GetDBObjectType(ds.Fields) in [NODETYPE_TABLE, NODETYPE_VIEW] then
comboTable.Items.Add(ds.FieldByName(DBO_NAME).AsWideString);
count := comboTable.Items.Count-1; count := comboTable.Items.Count-1;
if (comboDatabase.Text = seldb) and (comboTable.Items[count] = seltable) then if (comboDatabase.Text = seldb) and (comboTable.Items[count] = seltable) then
comboTable.ItemIndex := count; comboTable.ItemIndex := count;

View File

@ -320,7 +320,7 @@ object MainForm: TMainForm
object btnDBDropTable: TToolButton object btnDBDropTable: TToolButton
Left = 46 Left = 46
Top = 0 Top = 0
Action = actDropTablesAndViews Action = actDropDBobjects
end end
object btnDBCopyTable: TToolButton object btnDBCopyTable: TToolButton
Left = 69 Left = 69
@ -899,6 +899,7 @@ object MainForm: TMainForm
OnChange = ListTablesChange OnChange = ListTablesChange
OnCompareNodes = vstCompareNodes OnCompareNodes = vstCompareNodes
OnDblClick = ListTablesDblClick OnDblClick = ListTablesDblClick
OnEditing = ListTablesEditing
OnFreeNode = vstFreeNode OnFreeNode = vstFreeNode
OnGetText = vstGetText OnGetText = vstGetText
OnGetImageIndex = vstGetImageIndex OnGetImageIndex = vstGetImageIndex
@ -1025,6 +1026,18 @@ object MainForm: TMainForm
object tabTable: TTabSheet object tabTable: TTabSheet
Caption = 'Table' Caption = 'Table'
ImageIndex = 14 ImageIndex = 14
object lblSorryNoFields: TLabel
Left = 0
Top = 0
Width = 502
Height = 340
Align = alClient
Alignment = taCenter
Caption = 'Please use the stored routine editor to edit attributes.'
Layout = tlCenter
WordWrap = True
OnClick = actEditRoutineExecute
end
object ListColumns: TVirtualStringTree object ListColumns: TVirtualStringTree
Left = 0 Left = 0
Top = 0 Top = 0
@ -1099,6 +1112,17 @@ object MainForm: TMainForm
object tabData: TTabSheet object tabData: TTabSheet
Caption = 'Data' Caption = 'Data'
ImageIndex = 41 ImageIndex = 41
object lblSorryNoData: TLabel
Left = 0
Top = 91
Width = 502
Height = 249
Align = alClient
Alignment = taCenter
Caption = 'Stored routines don'#39't provide any data you could edit here.'
Layout = tlCenter
WordWrap = True
end
object pnlDataTop: TPanel object pnlDataTop: TPanel
Left = 0 Left = 0
Top = 0 Top = 0
@ -1631,7 +1655,7 @@ object MainForm: TMainForm
end end
object MenuDropTable: TMenuItem object MenuDropTable: TMenuItem
Tag = 32 Tag = 32
Action = actDropTablesAndViews Action = actDropDBobjects
end end
object N4: TMenuItem object N4: TMenuItem
Caption = '-' Caption = '-'
@ -1974,13 +1998,13 @@ object MainForm: TMainForm
ShortCut = 16463 ShortCut = 16463
OnExecute = actLoadSQLExecute OnExecute = actLoadSQLExecute
end end
object actDropTablesAndViews: TAction object actDropDBobjects: TAction
Category = 'Database' Category = 'Database'
Caption = 'Drop table/view ...' Caption = 'Drop ...'
Enabled = False Enabled = False
Hint = 'Deletes tables and/or views' Hint = 'Deletes tables, views, procedures and functions'
ImageIndex = 16 ImageIndex = 16
OnExecute = actDropTablesAndViewsExecute OnExecute = actDropDBobjectsExecute
end end
object actEditView: TAction object actEditView: TAction
Category = 'Database' Category = 'Database'
@ -2425,6 +2449,13 @@ object MainForm: TMainForm
ImageIndex = 119 ImageIndex = 119
OnExecute = actCreateRoutineExecute OnExecute = actCreateRoutineExecute
end end
object actEditRoutine: TAction
Category = 'Database'
Caption = 'Edit stored routine ...'
Hint = 'Edit stored procedure or function'
ImageIndex = 119
OnExecute = actEditRoutineExecute
end
end end
object SaveDialog2: TSaveDialog object SaveDialog2: TSaveDialog
DefaultExt = 'reg' DefaultExt = 'reg'
@ -5933,7 +5964,13 @@ object MainForm: TMainForm
Action = actEditView Action = actEditView
end end
object PopupMenuDropTable: TMenuItem object PopupMenuDropTable: TMenuItem
Action = actDropTablesAndViews Action = actDropDBobjects
end
object menuTreeCreateRoutine: TMenuItem
Action = actCreateRoutine
end
object menuTreeEditRoutine: TMenuItem
Action = actEditRoutine
end end
object Exporttables2: TMenuItem object Exporttables2: TMenuItem
Action = actExportTables Action = actExportTables
@ -5977,6 +6014,9 @@ object MainForm: TMainForm
object menuEditView: TMenuItem object menuEditView: TMenuItem
Action = actEditView Action = actEditView
end end
object menuEditRoutine: TMenuItem
Action = actEditRoutine
end
object InsertfilesintoBLOBfields1a: TMenuItem object InsertfilesintoBLOBfields1a: TMenuItem
Action = actInsertFiles Action = actInsertFiles
end end
@ -5984,7 +6024,7 @@ object MainForm: TMainForm
Caption = '-' Caption = '-'
end end
object menudroptablea: TMenuItem object menudroptablea: TMenuItem
Action = actDropTablesAndViews Action = actDropDBobjects
end end
object menuemptytable: TMenuItem object menuemptytable: TMenuItem
Action = actEmptyTables Action = actEmptyTables

View File

@ -113,7 +113,7 @@ type
actInsertFiles: TAction; actInsertFiles: TAction;
InsertfilesintoBLOBfields1: TMenuItem; InsertfilesintoBLOBfields1: TMenuItem;
actExportTables: TAction; actExportTables: TAction;
actDropTablesAndViews: TAction; actDropDBobjects: TAction;
actLoadSQL: TAction; actLoadSQL: TAction;
ImportSQL1: TMenuItem; ImportSQL1: TMenuItem;
menuConnections: TPopupMenu; menuConnections: TPopupMenu;
@ -460,6 +460,12 @@ type
actCreateRoutine1: TMenuItem; actCreateRoutine1: TMenuItem;
btnDBCreateRoutine: TToolButton; btnDBCreateRoutine: TToolButton;
btnExit: TToolButton; btnExit: TToolButton;
actEditRoutine: TAction;
menuTreeEditRoutine: TMenuItem;
menuTreeCreateRoutine: TMenuItem;
menuEditRoutine: TMenuItem;
lblSorryNoFields: TLabel;
lblSorryNoData: TLabel;
procedure refreshMonitorConfig; procedure refreshMonitorConfig;
procedure loadWindowConfig; procedure loadWindowConfig;
procedure saveWindowConfig; procedure saveWindowConfig;
@ -508,7 +514,7 @@ type
procedure actDataPostChangesExecute(Sender: TObject); procedure actDataPostChangesExecute(Sender: TObject);
procedure actDropDatabaseExecute(Sender: TObject); procedure actDropDatabaseExecute(Sender: TObject);
procedure actDropFieldsExecute(Sender: TObject); procedure actDropFieldsExecute(Sender: TObject);
procedure actDropTablesAndViewsExecute(Sender: TObject); procedure actDropDBobjectsExecute(Sender: TObject);
procedure actEditDatabaseExecute(Sender: TObject); procedure actEditDatabaseExecute(Sender: TObject);
procedure actEditIndexesExecute(Sender: TObject); procedure actEditIndexesExecute(Sender: TObject);
procedure actEmptyTablesExecute(Sender: TObject); procedure actEmptyTablesExecute(Sender: TObject);
@ -733,6 +739,9 @@ type
procedure EnumerateRecentFilters; procedure EnumerateRecentFilters;
procedure LoadRecentFilter(Sender: TObject); procedure LoadRecentFilter(Sender: TObject);
procedure actCreateRoutineExecute(Sender: TObject); procedure actCreateRoutineExecute(Sender: TObject);
procedure actEditRoutineExecute(Sender: TObject);
procedure ListTablesEditing(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; var Allowed: Boolean);
private private
FDelimiter: String; FDelimiter: String;
ServerUptime : Integer; ServerUptime : Integer;
@ -759,6 +768,7 @@ type
DataGridDB, DataGridTable : WideString; DataGridDB, DataGridTable : WideString;
PrevTableColWidths : WideStrings.TWideStringList; PrevTableColWidths : WideStrings.TWideStringList;
DataGridHasChanges : Boolean; DataGridHasChanges : Boolean;
InformationSchemaTables : TWideStringlist;
function GetParamValue(const paramChar: Char; const paramName: function GetParamValue(const paramChar: Char; const paramName:
string; var curIdx: Byte; out paramValue: string): Boolean; string; var curIdx: Byte; out paramValue: string): Boolean;
procedure SetDelimiter(Value: String); procedure SetDelimiter(Value: String);
@ -1750,6 +1760,7 @@ begin
ClearAllTableLists; ClearAllTableLists;
FreeAndNil(DatabasesWanted); FreeAndNil(DatabasesWanted);
FreeAndNil(Databases); FreeAndNil(Databases);
FreeAndNil(InformationSchemaTables);
// Closing connection // Closing connection
if Assigned(FMysqlConn) then begin if Assigned(FMysqlConn) then begin
@ -1934,7 +1945,7 @@ begin
// "Edit view" was clicked in DBTree's context menu // "Edit view" was clicked in DBTree's context menu
ds := FetchDbTableList(ActiveDatabase); ds := FetchDbTableList(ActiveDatabase);
ds.RecNo := DBtree.GetFirstSelected.Index+1; ds.RecNo := DBtree.GetFirstSelected.Index+1;
ViewForm.EditViewName := ds.Fields[0].AsString; ViewForm.EditViewName := ds.FieldByName(DBO_NAME).AsString;
end else end else
// If we're here, there's a menu item "Edit/Create view" in an unknown location // If we're here, there's a menu item "Edit/Create view" in an unknown location
raise Exception.Create('Internal error in actCreateViewExexute.'); raise Exception.Create('Internal error in actCreateViewExexute.');
@ -2328,11 +2339,34 @@ begin
end; end;
// Drop Table(s) // Drop Table(s)
procedure TMainForm.actDropTablesAndViewsExecute(Sender: TObject); procedure TMainForm.actDropDBobjectsExecute(Sender: TObject);
var var
i : Integer; AllCount : Integer;
Tables, Views : TWideStringList; Tables, Views, Functions, Procedures: TWideStringList;
msg, sql, activeDB : String; msg, activeDB : String;
procedure DoDrop(Kind: String; List: TWideStringlist; MultiDrops: Boolean);
var
i: Integer;
baseSql, sql: WideString;
begin
if List.Count > 0 then begin
baseSql := 'DROP '+Kind+' ';
sql := '';
for i := 0 to List.Count - 1 do begin
if (i > 0) and MultiDrops then sql := sql + ', ';
sql := sql + mask(List[i]);
if not MultiDrops then begin
ExecUpdateQuery(baseSql + sql);
sql := '';
end;
end;
if MultiDrops then
ExecUpdateQuery(baseSql + sql);
end;
FreeAndNil(List);
end;
begin begin
debug('drop table activated'); debug('drop table activated');
// Set default database name to to ActiveDatabase. // Set default database name to to ActiveDatabase.
@ -2341,61 +2375,50 @@ begin
Tables := TWideStringlist.Create; Tables := TWideStringlist.Create;
Views := TWideStringlist.Create; Views := TWideStringlist.Create;
Procedures := TWideStringlist.Create;
Functions := TWideStringlist.Create;
if (PageControlMain.ActivePage = tabDatabase) and if (PageControlMain.ActivePage = tabDatabase) and
((Sender as TAction).ActionComponent <> PopupMenuDropTable) then begin ((Sender as TAction).ActionComponent <> PopupMenuDropTable) then begin
// Invoked from one of the various buttons, SheetDatabase is the active page, drop highlighted table(s). // Invoked from one of the various buttons, SheetDatabase is the active page, drop highlighted table(s).
Tables := GetVTCaptions(ListTables, True, 0, NODETYPE_TABLE); Tables := GetVTCaptions(ListTables, True, 0, NODETYPE_TABLE);
Tables.AddStrings(GetVTCaptions(ListTables, True, 0, NODETYPE_CRASHED_TABLE)); Tables.AddStrings(GetVTCaptions(ListTables, True, 0, NODETYPE_CRASHED_TABLE));
Views := GetVTCaptions(ListTables, True, 0, NODETYPE_VIEW); Views := GetVTCaptions(ListTables, True, 0, NODETYPE_VIEW);
Procedures := GetVTCaptions(ListTables, True, 0, NODETYPE_PROCEDURE);
Functions := GetVTCaptions(ListTables, True, 0, NODETYPE_FUNCTION);
end else begin end else begin
// Invoked from one of the various buttons, drop table selected in tree view. // Invoked from one of the various buttons, drop table selected in tree view.
case GetSelectedNodeType of case GetSelectedNodeType of
NODETYPE_TABLE: Tables.Add(SelectedTable); NODETYPE_TABLE, NODETYPE_CRASHED_TABLE: Tables.Add(SelectedTable);
NODETYPE_CRASHED_TABLE: Tables.Add(SelectedTable); NODETYPE_VIEW: Views.Add(SelectedTable);
NODETYPE_VIEW: Views.Add(SelectedTable) NODETYPE_PROCEDURE: Procedures.Add(SelectedTable);
NODETYPE_FUNCTION: Functions.Add(SelectedTable);
end; end;
end; end;
// Fix actions temporarily enabled for popup menu. // Fix actions temporarily enabled for popup menu.
ValidateControls; ValidateControls;
AllCount := Tables.Count + Views.Count + Procedures.Count + Functions.Count;
// Safety stop to avoid firing DROP TABLE without tablenames // Safety stop to avoid firing DROP TABLE without tablenames
if (Tables.Count = 0) and (Views.Count = 0) then if (AllCount = 0) then
Exit; Exit;
// Ask user for confirmation to drop selected objects // Ask user for confirmation to drop selected objects
msg := 'Drop ' + IntToStr(Tables.Count+Views.Count) + ' table(s) and/or view(s) in database "'+activeDB+'"?' msg := 'Drop ' + IntToStr(AllCount) + ' object(s) in database "'+activeDB+'"?'
+ CRLF; + CRLF;
if Tables.Count > 0 then msg := msg + CRLF + 'Tables: ' + ImplodeStr(', ', Tables); if Tables.Count > 0 then msg := msg + CRLF + 'Table(s): ' + ImplodeStr(', ', Tables);
if Views.Count > 0 then msg := msg + CRLF + 'Views: ' + ImplodeStr(', ', Views); if Views.Count > 0 then msg := msg + CRLF + 'View(s): ' + ImplodeStr(', ', Views);
if Procedures.Count > 0 then msg := msg + CRLF + 'Procedure(s): ' + ImplodeStr(', ', Procedures);
if Functions.Count > 0 then msg := msg + CRLF + 'Function(s): ' + ImplodeStr(', ', Functions);
if MessageDlg(msg, mtConfirmation, [mbok,mbcancel], 0) <> mrok then if MessageDlg(msg, mtConfirmation, [mbok,mbcancel], 0) <> mrok then
Exit; Exit;
// Compose and run DROP TABLE query // Compose and run DROP [TABLE|VIEW|...] queries
if Tables.Count > 0 then begin DoDrop('TABLE', Tables, True);
sql := 'DROP TABLE '; DoDrop('VIEW', Views, True);
for i := 0 to Tables.Count - 1 do DoDrop('PROCEDURE', Procedures, False);
begin DoDrop('FUNCTION', Functions, False);
if i > 0 then
sql := sql + ', ';
sql := sql + mask(Tables[i]);
end;
ExecUpdateQuery( sql );
end;
FreeAndNil(Tables);
// Compose and run DROP VIEW query
if Views.Count > 0 then begin
sql := 'DROP VIEW ';
for i := 0 to Views.Count - 1 do
begin
if i > 0 then
sql := sql + ', ';
sql := sql + mask(Views[i]);
end;
ExecUpdateQuery( sql );
end;
FreeAndNil(Views);
// Refresh ListTables + dbtree so the dropped tables are gone: // Refresh ListTables + dbtree so the dropped tables are gone:
actRefresh.Execute; actRefresh.Execute;
@ -2673,10 +2696,18 @@ var
NodeData: PVTreeData; NodeData: PVTreeData;
begin begin
// table-doubleclick // table-doubleclick
if Assigned(ListTables.FocusedNode) then begin if not Assigned(ListTables.FocusedNode) then
NodeData := ListTables.GetNodeData(ListTables.FocusedNode); Exit;
SelectedTable := NodeData.Captions[0];
PageControlMain.ActivePage := tabTable; NodeData := ListTables.GetNodeData(ListTables.FocusedNode);
case NodeData.ImageIndex of
ICONINDEX_TABLE, ICONINDEX_CRASHED_TABLE, ICONINDEX_VIEW: begin
SelectedTable := NodeData.Captions[0];
PageControlMain.ActivePage := tabTable;
end;
ICONINDEX_STOREDPROCEDURE, ICONINDEX_STOREDFUNCTION: begin
actEditRoutine.Execute;
end;
end; end;
end; end;
@ -3578,14 +3609,25 @@ begin
if DataGridHasChanges then if DataGridHasChanges then
actDataPostChangesExecute(Sender); actDataPostChangesExecute(Sender);
// Ensure <Table> and <Data> are visible
tabTable.TabVisible := true;
tabData.TabVisible := true;
// Switch to <Data>
PageControlMain.ActivePage := tabData;
if not (GetSelectedNodeType in [NODETYPE_TABLE, NODETYPE_CRASHED_TABLE, NODETYPE_VIEW]) then begin
DataGrid.Hide; // Reveals lblSorryNoData
pnlDataTop.Hide;
pnlFilter.Hide;
Screen.Cursor := crDefault;
Exit;
end else begin
DataGrid.Show;
pnlFilter.Show;
pnlDataTop.Show;
end;
try try
if (SelectedTable <> '') and (ActiveDatabase <> '') then begin if (SelectedTable <> '') and (ActiveDatabase <> '') then begin
// Ensure <Table> and <Data> are visible
tabTable.TabVisible := true;
tabData.TabVisible := true;
// Switch to <Data>
PageControlMain.ActivePage := tabData;
if FDataGridSelect = nil then if FDataGridSelect = nil then
FDataGridSelect := WideStrings.TWideStringlist.Create; FDataGridSelect := WideStrings.TWideStringlist.Create;
if DataGridTable <> SelectedTable then begin if DataGridTable <> SelectedTable then begin
@ -3776,8 +3818,8 @@ begin
rows_total := -1; rows_total := -1;
IsInnodb := False; IsInnodb := False;
for i := 0 to ds.RecordCount - 1 do begin for i := 0 to ds.RecordCount - 1 do begin
if ds.Fields[0].AsWideString = SelectedTable then begin if ds.FieldByName(DBO_NAME).AsWideString = SelectedTable then begin
rows_total := MakeInt(ds.FieldByName('Rows').AsString); rows_total := MakeInt(ds.FieldByName(DBO_ROWS).AsString);
IsInnodb := ds.Fields[1].AsString = 'InnoDB'; IsInnodb := ds.Fields[1].AsString = 'InnoDB';
break; break;
end; end;
@ -3842,10 +3884,11 @@ begin
// Do this only if the user clicked the new tab. Not on automatic tab changes. // Do this only if the user clicked the new tab. Not on automatic tab changes.
if Sender = PageControlMain then begin if Sender = PageControlMain then begin
if tab = tabDatabase then ListTables.SetFocus if tab = tabDatabase then ListTables.SetFocus
else if tab = tabTable then ListColumns.SetFocus else if (tab = tabTable) and (ListColumns.Visible) then ListColumns.SetFocus
else if tab = tabData then begin else if tab = tabData then begin
viewdata(Sender); viewdata(Sender);
DataGrid.SetFocus; if DataGrid.Visible then
DataGrid.SetFocus;
end else if tab = tabQuery then SynMemoQuery.SetFocus; end else if tab = tabQuery then SynMemoQuery.SetFocus;
end; end;
@ -3888,6 +3931,8 @@ function TMainForm.FetchDbTableList(db: WideString): TDataSet;
var var
ds: TDataSet; ds: TDataSet;
OldCursor: TCursor; OldCursor: TCursor;
Unions: TWideStringlist;
ListObjectsSQL: WideString;
begin begin
if not DbTableListCached(db) then begin if not DbTableListCached(db) then begin
// Not in cache, load table list. // Not in cache, load table list.
@ -3895,12 +3940,74 @@ begin
Screen.Cursor := crHourGlass; Screen.Cursor := crHourGlass;
ShowStatus('Fetching tables from "' + db + '" ...'); ShowStatus('Fetching tables from "' + db + '" ...');
try try
ds := GetResults('SHOW TABLE STATUS FROM ' + mask(db), false, false); if not Assigned(InformationSchemaTables) then
InformationSchemaTables := GetCol('SHOW TABLES FROM '+mask(DBNAME_INFORMATION_SCHEMA), 0, True, False);
if InformationSchemaTables.IndexOf('TABLES') > -1 then begin
Unions := TWideStringlist.Create;
// Tables and (system) views
Unions.Add('SELECT TABLE_NAME AS '+mask(DBO_NAME)+
', TABLE_TYPE AS '+mask(DBO_TYPE)+
', ENGINE AS '+mask(DBO_ENGINE)+
', VERSION AS '+mask(DBO_VERSION)+
', ROW_FORMAT AS '+mask(DBO_ROWFORMAT)+
', TABLE_ROWS AS '+mask(DBO_ROWS)+
', AVG_ROW_LENGTH AS '+mask(DBO_AVGROWLEN)+
', DATA_LENGTH AS '+mask(DBO_DATALEN)+
', MAX_DATA_LENGTH AS '+mask(DBO_MAXDATALEN)+
', INDEX_LENGTH AS '+mask(DBO_INDEXLEN)+
', DATA_FREE AS '+mask(DBO_DATAFREE)+
', AUTO_INCREMENT AS '+mask(DBO_AUTOINC)+
', CREATE_TIME AS '+mask(DBO_CREATED)+
', UPDATE_TIME AS '+mask(DBO_UPDATED)+
', CHECK_TIME AS '+mask(DBO_CHECKED)+
', TABLE_COLLATION AS '+mask(DBO_COLLATION)+
', CHECKSUM AS '+mask(DBO_CHECKSUM)+
', CREATE_OPTIONS AS '+mask(DBO_CROPTIONS)+
', TABLE_COMMENT AS '+mask(DBO_COMMENT)+
' FROM '+mask(DBNAME_INFORMATION_SCHEMA)+'.TABLES ' +
'WHERE TABLE_SCHEMA = '+esc(db));
// Stored routines
if InformationSchemaTables.IndexOf('ROUTINES') > -1 then begin
Unions.Add('SELECT ROUTINE_NAME AS '+mask(DBO_NAME)+
', ROUTINE_TYPE AS '+mask(DBO_TYPE)+
', NULL AS '+mask(DBO_ENGINE)+
', NULL AS '+mask(DBO_VERSION)+
', NULL AS '+mask(DBO_ROWFORMAT)+
', NULL AS '+mask(DBO_ROWS)+
', NULL AS '+mask(DBO_AVGROWLEN)+
', NULL AS '+mask(DBO_DATALEN)+
', NULL AS '+mask(DBO_MAXDATALEN)+
', NULL AS '+mask(DBO_INDEXLEN)+
', NULL AS '+mask(DBO_DATAFREE)+
', NULL AS '+mask(DBO_AUTOINC)+
', CREATED AS '+mask(DBO_CREATED)+
', LAST_ALTERED AS '+mask(DBO_UPDATED)+
', NULL AS '+mask(DBO_CHECKED)+
', NULL AS '+mask(DBO_COLLATION)+
', NULL AS '+mask(DBO_CHECKSUM)+
', NULL AS '+mask(DBO_CROPTIONS)+
', ROUTINE_COMMENT AS '+mask(DBO_COMMENT)+
' FROM '+mask(DBNAME_INFORMATION_SCHEMA)+'.ROUTINES ' +
'WHERE ROUTINE_SCHEMA = '+esc(db));
end;
if Unions.Count = 1 then
ListObjectsSQL := Unions[0]
else
ListObjectsSQL := '(' + implodestr(') UNION (', Unions) + ')';
ListObjectsSQL := ListObjectsSQL + ' ORDER BY `Name`';
FreeAndNil(Unions);
end else begin
// For servers lacking the INFORMATION_SCHEMA or the TABLES table
ListObjectsSQL := 'SHOW TABLE STATUS FROM ' + mask(db);
end;
ds := GetResults(ListObjectsSQL);
CachedTableLists.AddObject(db, ds); CachedTableLists.AddObject(db, ds);
// Add table names to SQL highlighter // Add table names to SQL highlighter
SynSQLSyn1.TableNames.BeginUpdate; SynSQLSyn1.TableNames.BeginUpdate;
while not ds.Eof do begin while not ds.Eof do begin
SynSQLSyn1.TableNames.Add(ds.Fields[0].AsWideString); SynSQLSyn1.TableNames.Add(ds.FieldByName(DBO_NAME).AsWideString);
ds.Next; ds.Next;
end; end;
SynSQLSyn1.TableNames.EndUpdate; SynSQLSyn1.TableNames.EndUpdate;
@ -3977,7 +4084,7 @@ var
i : Integer; i : Integer;
bytes : Int64; bytes : Int64;
ds : TDataSet; ds : TDataSet;
ListCaptions, Cap,
SelectedCaptions: WideStrings.TWideStringList; SelectedCaptions: WideStrings.TWideStringList;
begin begin
// DB-Properties // DB-Properties
@ -3986,145 +4093,89 @@ begin
// Remember selected nodes // Remember selected nodes
SelectedCaptions := GetVTCaptions(ListTables, True); SelectedCaptions := GetVTCaptions(ListTables, True);
try ds := FetchDbTableList(db);
ds := FetchDbTableList(db); ShowStatus( 'Displaying tables from "' + db + '" ...' );
ShowStatus( 'Displaying tables from "' + db + '" ...' );
ListTables.BeginUpdate; ListTables.BeginUpdate;
ListTables.Clear; ListTables.Clear;
SetLength(VTRowDataListTables, ds.RecordCount); SetLength(VTRowDataListTables, ds.RecordCount);
for i := 1 to ds.RecordCount do for i := 1 to ds.RecordCount do
begin begin
listcaptions := WideStrings.TWideStringList.Create; VTRowDataListTables[i-1].Captions := WideStrings.TWideStringList.Create;
// Table Cap := VTRowDataListTables[i-1].Captions;
ListCaptions.Add( ds.Fields[0].AsWideString ); // Object name
Cap.Add( FieldContent(ds, DBO_NAME) );
if (FieldContent(ds, DBO_ROWS) <> '') then
Cap.Add( FormatNumber( FieldContent(ds, DBO_ROWS) ) )
else Cap.Add('');
// Size: Data_length + Index_length
bytes := GetTableSize(ds);
if bytes >= 0 then Cap.Add(FormatByteNumber(bytes))
else Cap.Add('');
Cap.Add( FieldContent(ds, DBO_CREATED) );
Cap.Add( FieldContent(ds, DBO_UPDATED) );
Cap.Add( FieldContent(ds, DBO_ENGINE) );
Cap.Add( FieldContent(ds, DBO_COMMENT) );
Cap.Add( FieldContent(ds, DBO_VERSION) );
Cap.Add( FieldContent(ds, DBO_ROWFORMAT) );
if (FieldContent(ds, DBO_AVGROWLEN) <> '') then
Cap.Add( FormatByteNumber(FieldContent(ds, DBO_AVGROWLEN)) )
else Cap.Add('');
if (FieldContent(ds, DBO_MAXDATALEN) <> '') then
Cap.Add( FormatByteNumber(FieldContent(ds, DBO_MAXDATALEN)) )
else Cap.Add('');
if (FieldContent(ds, DBO_INDEXLEN) <> '') then
Cap.Add( FormatByteNumber(FieldContent(ds, DBO_INDEXLEN)) )
else Cap.Add('');
if (FieldContent(ds, DBO_DATAFREE) <> '') then
Cap.Add( FormatByteNumber(FieldContent(ds, DBO_DATAFREE)) )
else Cap.Add('');
if (FieldContent(ds, DBO_AUTOINC) <> '') then
Cap.Add( FormatNumber(FieldContent(ds, DBO_AUTOINC)) )
else Cap.Add('');
Cap.Add( FieldContent(ds, DBO_AUTOINC) );
Cap.Add( FieldContent(ds, DBO_COLLATION) );
Cap.Add( FieldContent(ds, DBO_CHECKSUM) );
Cap.Add( FieldContent(ds, DBO_CROPTIONS) );
if ds.FindField(DBO_TYPE) <> nil then
Cap.Add(FieldContent(ds, DBO_TYPE))
else
Cap.Add('BASE TABLE');
// Treat tables slightly different than views VTRowDataListTables[i-1].NodeType := GetDBObjectType( ds.Fields);
case GetDBObjectType( ds.Fields) of // Find icon
NODETYPE_TABLE, NODETYPE_CRASHED_TABLE: // A normal table case VTRowDataListTables[i-1].NodeType of
begin NODETYPE_TABLE, NODETYPE_CRASHED_TABLE: // A normal table
if GetDBObjectType(ds.Fields) = NODETYPE_CRASHED_TABLE then begin begin
VTRowDataListTables[i-1].ImageIndex := ICONINDEX_CRASHED_TABLE; if GetDBObjectType(ds.Fields) = NODETYPE_CRASHED_TABLE then
VTRowDataListTables[i-1].NodeType := NODETYPE_CRASHED_TABLE; VTRowDataListTables[i-1].ImageIndex := ICONINDEX_CRASHED_TABLE
end else begin else
VTRowDataListTables[i-1].ImageIndex := ICONINDEX_TABLE; VTRowDataListTables[i-1].ImageIndex := ICONINDEX_TABLE;
VTRowDataListTables[i-1].NodeType := NODETYPE_TABLE;
end;
// Rows
if ds.FindField('Rows') <> nil then
ListCaptions.Add( FormatNumber( FieldContent(ds, 'Rows') ) )
else
ListCaptions.Add('');
// Size: Data_length + Index_length
bytes := GetTableSize(ds);
if bytes >= 0 then ListCaptions.Add(FormatByteNumber(bytes))
else ListCaptions.Add('');
// Created:
ListCaptions.Add( FieldContent(ds, 'Create_time') );
// Updated:
ListCaptions.Add( FieldContent(ds, 'Update_time') );
// Engine
if ds.FindField('Type') <> nil then
ListCaptions.Add( FieldContent(ds, 'Type') )
else
ListCaptions.Add( FieldContent(ds, 'Engine') );
// Comment
ListCaptions.Add( FieldContent(ds, 'Comment') );
// Version
ListCaptions.Add( FieldContent(ds, 'Version') );
// Row format
ListCaptions.Add( FieldContent(ds, 'Row_format') );
// Avg row length
if (FieldContent(ds, 'Avg_row_length') <> '') then
ListCaptions.Add( FormatByteNumber(FieldContent(ds, 'Avg_row_length')) )
else ListCaptions.Add('');
// Max data length
if (FieldContent(ds, 'Max_data_length') <> '') then
ListCaptions.Add( FormatByteNumber(FieldContent(ds, 'Max_data_length')) )
else ListCaptions.Add('');
// Index length
if (FieldContent(ds, 'Index_length') <> '') then
ListCaptions.Add( FormatByteNumber(FieldContent(ds, 'Index_length')) )
else ListCaptions.Add('');
// Data free
if (FieldContent(ds, 'Data_free') <> '') then
ListCaptions.Add( FormatByteNumber(FieldContent(ds, 'Data_free')) )
else ListCaptions.Add('');
// Auto increment
if (FieldContent(ds, 'Auto_increment') <> '') then
ListCaptions.Add( FormatNumber(FieldContent(ds, 'Auto_increment')) )
else ListCaptions.Add('');
// Check time
ListCaptions.Add( FieldContent(ds, 'Check_time') );
// Collation
ListCaptions.Add( FieldContent(ds, 'Collation') );
// Checksum
ListCaptions.Add( FieldContent(ds, 'Checksum') );
// Create_options
ListCaptions.Add( FieldContent(ds, 'Create_options') );
// Object type
ListCaptions.Add('Base table');
end;
NODETYPE_VIEW:
begin // View
VTRowDataListTables[i-1].ImageIndex := ICONINDEX_VIEW;
VTRowDataListTables[i-1].NodeType := NODETYPE_VIEW;
// Rows
ListCaptions.Add('');
// Size
ListCaptions.Add('');
// Created:
ListCaptions.Add('');
// Updated:
ListCaptions.Add('');
// Engine
ListCaptions.Add('');
// Comment
ListCaptions.Add(FieldContent(ds, 'Comment'));
// Version
ListCaptions.Add('');
// Row_format
ListCaptions.Add('');
// Avg_row_length
ListCaptions.Add('');
// Max_data_length
ListCaptions.Add('');
// Index_length
ListCaptions.Add('');
// Data_free
ListCaptions.Add('');
// Auto_increment
ListCaptions.Add('');
// Check_time
ListCaptions.Add('');
// Collation
ListCaptions.Add('');
// Checksum
ListCaptions.Add('');
// Create_options
ListCaptions.Add('');
// Object Type
ListCaptions.Add('View');
end;
end; end;
VTRowDataListTables[i-1].Captions := ListCaptions; NODETYPE_VIEW:
ds.Next; VTRowDataListTables[i-1].ImageIndex := ICONINDEX_VIEW;
NODETYPE_PROCEDURE:
VTRowDataListTables[i-1].ImageIndex := ICONINDEX_STOREDPROCEDURE;
NODETYPE_FUNCTION:
VTRowDataListTables[i-1].ImageIndex := ICONINDEX_STOREDFUNCTION;
end; end;
finally
ListTables.RootNodeCount := Length(VTRowDataListTables); ds.Next;
ListTables.EndUpdate;
SetVTSelection(ListTables, SelectedCaptions);
showstatus(db + ': ' + IntToStr(ListTables.RootNodeCount) +' table(s)', 0);
tabDatabase.Caption := sstr('Database: ' + db, 30);
ShowStatus(STATUS_MSG_READY);
Screen.Cursor := crDefault;
// Ensure tree db node displays its chidren initialized
DBtree.ReinitChildren(FindDBNode(db), False);
ValidateControls;
end; end;
ListTables.RootNodeCount := Length(VTRowDataListTables);
ListTables.EndUpdate;
SetVTSelection(ListTables, SelectedCaptions);
showstatus(db + ': ' + IntToStr(ListTables.RootNodeCount) +' table(s)', 0);
tabDatabase.Caption := sstr('Database: ' + db, 30);
ShowStatus(STATUS_MSG_READY);
Screen.Cursor := crDefault;
// Ensure tree db node displays its chidren initialized
DBtree.ReinitChildren(FindDBNode(db), False);
ValidateControls;
end; end;
@ -4145,13 +4196,31 @@ var
dummy: Boolean; dummy: Boolean;
hasCommentColumn: Boolean; hasCommentColumn: Boolean;
SelectedCaptions: WideStrings.TWideStringList; SelectedCaptions: WideStrings.TWideStringList;
defaultVal: WideString; defaultVal, cap: WideString;
begin begin
// Table-Properties // Table-Properties
dataselected := false; dataselected := false;
Screen.Cursor := crHourGlass; Screen.Cursor := crHourGlass;
tabTable.Caption := sstr('Table: ' + SelectedTable, 30); case GetSelectedNodeType of
NODETYPE_TABLE, NODETYPE_CRASHED_TABLE: begin
cap := 'Table';
tabTable.ImageIndex := ICONINDEX_TABLE;
end;
NODETYPE_VIEW: begin
cap := 'View';
tabTable.ImageIndex := ICONINDEX_VIEW;
end;
NODETYPE_PROCEDURE: begin
cap := 'Procedure';
tabTable.ImageIndex := ICONINDEX_STOREDPROCEDURE;
end;
NODETYPE_FUNCTION: begin
cap := 'Function';
tabTable.ImageIndex := ICONINDEX_STOREDFUNCTION;
end;
end;
tabTable.Caption := sstr(cap+': ' + SelectedTable, 30);
tabDatabase.TabVisible := true; tabDatabase.TabVisible := true;
tabTable.TabVisible := true; tabTable.TabVisible := true;
@ -4162,6 +4231,13 @@ begin
(PageControlMain.ActivePage = tabDatabase) (PageControlMain.ActivePage = tabDatabase)
) then PageControlMain.ActivePage := tabTable; ) then PageControlMain.ActivePage := tabTable;
if not (GetSelectedNodeType in [NODETYPE_TABLE, NODETYPE_CRASHED_TABLE, NODETYPE_VIEW]) then begin
ListColumns.Hide; // Reveals lblSorryNoFields
Screen.Cursor := crDefault;
Exit;
end else
ListColumns.Show;
ShowStatus( 'Reading table properties...' ); ShowStatus( 'Reading table properties...' );
// Remember selected nodes // Remember selected nodes
SelectedCaptions := GetVTCaptions(ListColumns, True); SelectedCaptions := GetVTCaptions(ListColumns, True);
@ -4334,7 +4410,7 @@ end;
} }
procedure TMainForm.ValidateControls( FrmIsFocussed: Boolean = true ); procedure TMainForm.ValidateControls( FrmIsFocussed: Boolean = true );
var var
DBObjectSelected, TableSelected, ViewSelected, DBObjectSelected, TableSelected, ViewSelected, RoutineSelected,
inDbTab, inTableTab, inDataTab, inQueryTab, inDataOrQueryTab, inDataOrQueryTabNotEmpty, inDbTab, inTableTab, inDataTab, inQueryTab, inDataOrQueryTab, inDataOrQueryTabNotEmpty,
FieldsSelected, FieldFocused, dummy, DBfocused : Boolean; FieldsSelected, FieldFocused, dummy, DBfocused : Boolean;
NodeData: PVTreeData; NodeData: PVTreeData;
@ -4351,12 +4427,14 @@ begin
DBObjectSelected := (Length(SelectedNodes)>0) and FrmIsFocussed; DBObjectSelected := (Length(SelectedNodes)>0) and FrmIsFocussed;
TableSelected := False; TableSelected := False;
ViewSelected := False; ViewSelected := False;
RoutineSelected := False;
// Check type of first selected node, to en-/disable certain menu items // Check type of first selected node, to en-/disable certain menu items
if DBObjectSelected then begin if DBObjectSelected then begin
NodeData := ListTables.GetNodeData( SelectedNodes[0] ); NodeData := ListTables.GetNodeData( SelectedNodes[0] );
TableSelected := (NodeData.NodeType = NODETYPE_TABLE) or (NodeData.NodeType = NODETYPE_CRASHED_TABLE); TableSelected := (NodeData.NodeType = NODETYPE_TABLE) or (NodeData.NodeType = NODETYPE_CRASHED_TABLE);
ViewSelected := NodeData.NodeType = NODETYPE_VIEW; ViewSelected := NodeData.NodeType = NODETYPE_VIEW;
RoutineSelected := NodeData.NodeType in [NODETYPE_PROCEDURE, NODETYPE_FUNCTION];
end; end;
// Standard toolbar and main menu // Standard toolbar and main menu
@ -4380,9 +4458,10 @@ begin
// Database tab // Database tab
actEmptyTables.Enabled := inDbTab and TableSelected; actEmptyTables.Enabled := inDbTab and TableSelected;
actEditTableProperties.Enabled := inDbTab and TableSelected; actEditTableProperties.Enabled := inDbTab and TableSelected;
MenuRenameTable.Enabled := inDbTab and DBObjectSelected; MenuRenameTable.Enabled := inDbTab and (TableSelected or ViewSelected);
actCopyTable.Enabled := inDbTab and DBObjectSelected; actCopyTable.Enabled := inDbTab and (TableSelected or ViewSelected);
actEditView.Enabled := inDbTab and ViewSelected and (mysql_version >= 50001); actEditView.Enabled := inDbTab and ViewSelected and (mysql_version >= 50001);
actEditRoutine.Enabled := inDbTab and RoutineSelected and (mysql_version >= 50003);
actCreateView.Enabled := FrmIsFocussed and (ActiveDatabase <> '') and (mysql_version >= 50001); actCreateView.Enabled := FrmIsFocussed and (ActiveDatabase <> '') and (mysql_version >= 50001);
actCreateRoutine.Enabled := FrmIsFocussed and (ActiveDatabase <> '') and (mysql_version >= 50003); actCreateRoutine.Enabled := FrmIsFocussed and (ActiveDatabase <> '') and (mysql_version >= 50003);
actCreateDatabase.Enabled := FrmIsFocussed; actCreateDatabase.Enabled := FrmIsFocussed;
@ -4393,7 +4472,7 @@ begin
actEditDatabase.Hint := STR_NOTSUPPORTED actEditDatabase.Hint := STR_NOTSUPPORTED
else else
actEditDatabase.Hint := 'Rename and/or modify character set of database'; actEditDatabase.Hint := 'Rename and/or modify character set of database';
actDropTablesAndViews.Enabled := (DBObjectSelected and inDbTab) or ((not inQueryTab) and (SelectedTable <> '') and FrmIsFocussed); actDropDBobjects.Enabled := (DBObjectSelected and inDbTab) or ((not inQueryTab) and (SelectedTable <> '') and FrmIsFocussed);
actCreateTable.Enabled := (ActiveDatabase <> '') and FrmIsFocussed; actCreateTable.Enabled := (ActiveDatabase <> '') and FrmIsFocussed;
actEditTableFields.Enabled := DBObjectSelected and inDbTab; actEditTableFields.Enabled := DBObjectSelected and inDbTab;
@ -4932,6 +5011,17 @@ begin
end; end;
procedure TMainForm.ListTablesEditing(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex; var Allowed: Boolean);
var
NodeData: PVTreeData;
begin
// Tables and views can be renamed, routines cannot
NodeData := Sender.GetNodeData(Node);
Allowed := NodeData.ImageIndex in [ICONINDEX_TABLE, ICONINDEX_VIEW];
end;
{*** {***
Rename table after checking the new name for invalid characters Rename table after checking the new name for invalid characters
} }
@ -5257,9 +5347,11 @@ begin
L := DBtree.GetNodeLevel(DBtree.GetFirstSelected); L := DBtree.GetNodeLevel(DBtree.GetFirstSelected);
actCreateTable.Enabled := L in [1,2]; actCreateTable.Enabled := L in [1,2];
actCreateView.Enabled := (L in [1,2]) and (mysql_version >= 50001); actCreateView.Enabled := (L in [1,2]) and (mysql_version >= 50001);
actCreateRoutine.Enabled := (L in [1,2]) and (mysql_version >= 50003);
actEditTableProperties.Enabled := (L = 2) and ((GetSelectedNodeType = NODETYPE_TABLE) or (GetSelectedNodeType = NODETYPE_CRASHED_TABLE)); actEditTableProperties.Enabled := (L = 2) and ((GetSelectedNodeType = NODETYPE_TABLE) or (GetSelectedNodeType = NODETYPE_CRASHED_TABLE));
actEditView.Enabled := (L = 2) and (GetSelectedNodeType = NODETYPE_VIEW); actEditView.Enabled := (L = 2) and (GetSelectedNodeType = NODETYPE_VIEW);
actDropTablesAndViews.Enabled := (L = 2); actEditRoutine.Enabled := (L = 2) and (GetSelectedNodeType in [NODETYPE_PROCEDURE, NODETYPE_FUNCTION]);
actDropDBobjects.Enabled := (L = 2);
end; end;
@ -6940,7 +7032,7 @@ begin
2: begin 2: begin
ds := FetchDbTableList(Databases[Node.Parent.Index]); ds := FetchDbTableList(Databases[Node.Parent.Index]);
ds.RecNo := Node.Index+1; ds.RecNo := Node.Index+1;
CellText := ds.Fields[0].AsWideString; CellText := ds.FieldByName(DBO_NAME).AsWideString;
end; end;
end; end;
1: case GetNodeType(Node) of 1: case GetNodeType(Node) of
@ -7032,6 +7124,10 @@ begin
if Kind = ikSelected then if Kind = ikSelected then
ImageIndex := ICONINDEX_CRASHED_TABLE_HIGHLIGHT ImageIndex := ICONINDEX_CRASHED_TABLE_HIGHLIGHT
else ImageIndex := ICONINDEX_CRASHED_TABLE; else ImageIndex := ICONINDEX_CRASHED_TABLE;
NODETYPE_PROCEDURE:
ImageIndex := ICONINDEX_STOREDPROCEDURE;
NODETYPE_FUNCTION:
ImageIndex := ICONINDEX_STOREDFUNCTION;
end; end;
end; end;
end; end;
@ -9024,5 +9120,22 @@ begin
end; end;
procedure TMainForm.actEditRoutineExecute(Sender: TObject);
var
NodeData: PVTreeData;
begin
if not Assigned(RoutineEditForm) then
RoutineEditForm := TfrmRoutineEditor.Create(Self);
if ListTables.Focused then begin
NodeData := ListTables.GetNodeData( ListTables.FocusedNode );
RoutineEditForm.AlterRoutineName := NodeData.Captions[0];
end else
RoutineEditForm.AlterRoutineName := SelectedTable;
RoutineEditForm.ShowModal;
end;
end. end.

View File

@ -121,7 +121,8 @@ begin
ds := Mainform.FetchDbTableList(DBComboBox.Text); ds := Mainform.FetchDbTableList(DBComboBox.Text);
TablesCheckListBox.Items.Clear; TablesCheckListBox.Items.Clear;
while not ds.Eof do begin while not ds.Eof do begin
TablesCheckListBox.Items.Add(ds.Fields[0].AsWideString); if GetDBObjectType(ds.Fields) = NODETYPE_TABLE then
TablesCheckListBox.Items.Add(ds.FieldByName(DBO_NAME).AsWideString);
ds.Next; ds.Next;
end; end;
// Check all // Check all

View File

@ -206,7 +206,7 @@ begin
ds.RecNo := Node.Index+1; ds.RecNo := Node.Index+1;
cols := Mainform.GetCol('SHOW COLUMNS FROM ' cols := Mainform.GetCol('SHOW COLUMNS FROM '
+ Mainform.mask(Mainform.Databases[Node.Parent.Index])+'.' + Mainform.mask(Mainform.Databases[Node.Parent.Index])+'.'
+ Mainform.Mask(ds.Fields[0].AsWideString)); + Mainform.Mask(ds.FieldByName(DBO_NAME).AsWideString));
FColumns[Node.Parent.Index][Node.Index] := cols; FColumns[Node.Parent.Index][Node.Index] := cols;
ChildCount := cols.Count; ChildCount := cols.Count;
end; end;
@ -226,7 +226,7 @@ begin
1: begin 1: begin
ds := Mainform.FetchDbTableList(Mainform.Databases[Node.Parent.Index]); ds := Mainform.FetchDbTableList(Mainform.Databases[Node.Parent.Index]);
ds.RecNo := Node.Index+1; ds.RecNo := Node.Index+1;
CellText := ds.Fields[0].AsWideString; CellText := ds.FieldByName(DBO_NAME).AsWideString;
end; end;
2: CellText := FColumns[Node.Parent.Parent.Index][Node.Parent.Index][Node.Index]; 2: CellText := FColumns[Node.Parent.Parent.Index][Node.Parent.Index][Node.Index];
end; end;